RSVP untuk acara TensorFlow Everywhere lokal Anda hari ini!
Halaman ini diterjemahkan oleh Cloud Translation API.
Switch to English

Panduan pelatihan model

Lihat di TensorFlow.org Jalankan di Google Colab Lihat sumber di GitHub

Panduan ini memperkenalkan Swift untuk TensorFlow dengan membuat model pembelajaran mesin yang mengategorikan bunga iris menurut spesies. Ini menggunakan Swift untuk TensorFlow untuk:

  1. Bangun model,
  2. Latih model ini pada contoh data, dan
  3. Gunakan model untuk membuat prediksi tentang data yang tidak diketahui.

Pemrograman TensorFlow

Panduan ini menggunakan konsep Swift tingkat tinggi untuk TensorFlow:

  • Impor data dengan Epochs API.
  • Buat model menggunakan abstraksi Swift.
  • Gunakan pustaka Python menggunakan interoperabilitas Python Swift saat pustaka Swift murni tidak tersedia.

Tutorial ini disusun seperti banyak program TensorFlow:

  1. Impor dan parse kumpulan data.
  2. Pilih jenis model.
  3. Latih modelnya.
  4. Evaluasi efektivitas model.
  5. Gunakan model terlatih untuk membuat prediksi.

Program penataan

Konfigurasi impor

Impor TensorFlow dan beberapa modul Python yang berguna.

import TensorFlow
import PythonKit
// This cell is here to display the plots in a Jupyter Notebook.
// Do not copy it into another environment.
%include "EnableIPythonDisplay.swift"
print(IPythonDisplay.shell.enable_matplotlib("inline"))
('inline', 'module://ipykernel.pylab.backend_inline')

let plt = Python.import("matplotlib.pyplot")
import Foundation
import FoundationNetworking
func download(from sourceString: String, to destinationString: String) {
    let source = URL(string: sourceString)!
    let destination = URL(fileURLWithPath: destinationString)
    let data = try! Data.init(contentsOf: source)
    try! data.write(to: destination)
}

Masalah klasifikasi iris

Bayangkan Anda adalah seorang ahli botani yang mencari cara otomatis untuk mengkategorikan setiap bunga iris yang Anda temukan. Pembelajaran mesin menyediakan banyak algoritme untuk mengklasifikasikan bunga secara statistik. Misalnya, program pembelajaran mesin yang canggih dapat mengklasifikasikan bunga berdasarkan foto. Ambisi kami lebih sederhana — kami akan mengklasifikasikan bunga iris berdasarkan ukuran panjang dan lebar sepal dan kelopaknya .

Genus Iris memerlukan sekitar 300 spesies, tetapi program kami hanya akan mengklasifikasikan tiga spesies berikut:

  • Iris setosa
  • Iris virginica
  • Iris versicolor
Geometri kelopak dibandingkan untuk tiga spesies iris: Iris setosa, Iris virginica, dan Iris versicolor
Gambar 1. Iris setosa (oleh Radomil , CC BY-SA 3.0), Iris versicolor , (oleh Dlanglois , CC BY-SA 3.0), dan Iris virginica (oleh Frank Mayfield , CC BY-SA 2.0).

Untungnya, seseorang telah membuat kumpulan data 120 bunga iris dengan ukuran sepal dan kelopak. Ini adalah kumpulan data klasik yang populer untuk masalah klasifikasi pembelajaran mesin pemula.

Impor dan parse set data pelatihan

Unduh file dataset dan ubah menjadi struktur yang dapat digunakan oleh program Swift ini.

Unduh kumpulan data

Unduh file set data pelatihan dari http://download.tensorflow.org/data/iris_training.csv

let trainDataFilename = "iris_training.csv"
download(from: "http://download.tensorflow.org/data/iris_training.csv", to: trainDataFilename)

Periksa datanya

iris_training.csv data ini, iris_training.csv , adalah file teks biasa yang menyimpan data tabel yang diformat sebagai nilai yang dipisahkan koma (CSV). Mari kita lihat 5 entri pertama.

let f = Python.open(trainDataFilename)
for _ in 0..<5 {
    print(Python.next(f).strip())
}
print(f.close())
120,4,setosa,versicolor,virginica
6.4,2.8,5.6,2.2,2
5.0,2.3,3.3,1.0,1
4.9,2.5,4.5,1.7,2
4.9,3.1,1.5,0.1,0
None

Dari tampilan kumpulan data ini, perhatikan hal berikut:

  1. Baris pertama adalah header yang berisi informasi tentang dataset:
    • Ada total 120 contoh. Setiap contoh memiliki empat fitur dan satu dari tiga kemungkinan nama label.
  2. Baris berikutnya adalah catatan data, satu contoh per baris, di mana:
    • Empat bidang pertama adalah fitur : ini adalah karakteristik contoh. Di sini, bidang menyimpan angka float yang mewakili ukuran bunga.
    • Kolom terakhir adalah label : ini adalah nilai yang ingin kita prediksi. Untuk kumpulan data ini, ini adalah nilai integer 0, 1, atau 2 yang sesuai dengan nama bunga.

Mari kita tulis dalam kode:

let featureNames = ["sepal_length", "sepal_width", "petal_length", "petal_width"]
let labelName = "species"
let columnNames = featureNames + [labelName]

print("Features: \(featureNames)")
print("Label: \(labelName)")
Features: ["sepal_length", "sepal_width", "petal_length", "petal_width"]
Label: species

Setiap label dikaitkan dengan nama string (misalnya, "setosa"), tetapi pembelajaran mesin biasanya bergantung pada nilai numerik. Nomor label dipetakan ke representasi bernama, seperti:

  • 0 : Iris setosa
  • 1 : Iris versicolor
  • 2 : Iris virginica

Untuk informasi selengkapnya tentang fitur dan label, lihat bagian Terminologi ML dari Kursus Singkat Machine Learning .

let classNames = ["Iris setosa", "Iris versicolor", "Iris virginica"]

Buat set data menggunakan Epochs API

API Epochs Swift untuk TensorFlow adalah API tingkat tinggi untuk membaca data dan mengubahnya menjadi bentuk yang digunakan untuk pelatihan.

let batchSize = 32

/// A batch of examples from the iris dataset.
struct IrisBatch {
    /// [batchSize, featureCount] tensor of features.
    let features: Tensor<Float>

    /// [batchSize] tensor of labels.
    let labels: Tensor<Int32>
}

/// Conform `IrisBatch` to `Collatable` so that we can load it into a `TrainingEpoch`.
extension IrisBatch: Collatable {
    public init<BatchSamples: Collection>(collating samples: BatchSamples)
        where BatchSamples.Element == Self {
        /// `IrisBatch`es are collated by stacking their feature and label tensors
        /// along the batch axis to produce a single feature and label tensor
        features = Tensor<Float>(stacking: samples.map{$0.features})
        labels = Tensor<Int32>(stacking: samples.map{$0.labels})
    }
}

Karena dataset yang kita unduh dalam format CSV, mari kita tulis fungsi untuk memuat data sebagai daftar objek IrisBatch

/// Initialize an `IrisBatch` dataset from a CSV file.
func loadIrisDatasetFromCSV(
        contentsOf: String, hasHeader: Bool, featureColumns: [Int], labelColumns: [Int]) -> [IrisBatch] {
        let np = Python.import("numpy")

        let featuresNp = np.loadtxt(
            contentsOf,
            delimiter: ",",
            skiprows: hasHeader ? 1 : 0,
            usecols: featureColumns,
            dtype: Float.numpyScalarTypes.first!)
        guard let featuresTensor = Tensor<Float>(numpy: featuresNp) else {
            // This should never happen, because we construct featuresNp in such a
            // way that it should be convertible to tensor.
            fatalError("np.loadtxt result can't be converted to Tensor")
        }

        let labelsNp = np.loadtxt(
            contentsOf,
            delimiter: ",",
            skiprows: hasHeader ? 1 : 0,
            usecols: labelColumns,
            dtype: Int32.numpyScalarTypes.first!)
        guard let labelsTensor = Tensor<Int32>(numpy: labelsNp) else {
            // This should never happen, because we construct labelsNp in such a
            // way that it should be convertible to tensor.
            fatalError("np.loadtxt result can't be converted to Tensor")
        }

        return zip(featuresTensor.unstacked(), labelsTensor.unstacked()).map{IrisBatch(features: $0.0, labels: $0.1)}

    }

Sekarang kita dapat menggunakan fungsi pemuatan CSV untuk memuat set data pelatihan dan membuat objek TrainingEpochs

let trainingDataset: [IrisBatch] = loadIrisDatasetFromCSV(contentsOf: trainDataFilename, 
                                                  hasHeader: true, 
                                                  featureColumns: [0, 1, 2, 3], 
                                                  labelColumns: [4])

let trainingEpochs: TrainingEpochs = TrainingEpochs(samples: trainingDataset, batchSize: batchSize)

Objek TrainingEpochs adalah urutan epoch yang tak terbatas. Setiap epoch berisi IrisBatch es. Mari kita lihat elemen pertama dari zaman pertama.

let firstTrainEpoch = trainingEpochs.next()!
let firstTrainBatch = firstTrainEpoch.first!.collated
let firstTrainFeatures = firstTrainBatch.features
let firstTrainLabels = firstTrainBatch.labels

print("First batch of features: \(firstTrainFeatures)")
print("firstTrainFeatures.shape: \(firstTrainFeatures.shape)")
print("First batch of labels: \(firstTrainLabels)")
print("firstTrainLabels.shape: \(firstTrainLabels.shape)")
First batch of features: [[5.1, 2.5, 3.0, 1.1],
 [6.4, 3.2, 4.5, 1.5],
 [4.9, 3.1, 1.5, 0.1],
 [5.0, 2.0, 3.5, 1.0],
 [6.3, 2.5, 5.0, 1.9],
 [6.7, 3.1, 5.6, 2.4],
 [4.9, 3.1, 1.5, 0.1],
 [7.7, 2.8, 6.7, 2.0],
 [6.7, 3.0, 5.0, 1.7],
 [7.2, 3.6, 6.1, 2.5],
 [4.8, 3.0, 1.4, 0.1],
 [5.2, 3.4, 1.4, 0.2],
 [5.0, 3.5, 1.3, 0.3],
 [4.9, 3.1, 1.5, 0.1],
 [5.0, 3.5, 1.6, 0.6],
 [6.7, 3.3, 5.7, 2.1],
 [7.7, 3.8, 6.7, 2.2],
 [6.2, 3.4, 5.4, 2.3],
 [4.8, 3.4, 1.6, 0.2],
 [6.0, 2.9, 4.5, 1.5],
 [5.0, 3.0, 1.6, 0.2],
 [6.3, 3.4, 5.6, 2.4],
 [5.1, 3.8, 1.9, 0.4],
 [4.8, 3.1, 1.6, 0.2],
 [7.6, 3.0, 6.6, 2.1],
 [5.7, 3.0, 4.2, 1.2],
 [6.3, 3.3, 6.0, 2.5],
 [5.6, 2.5, 3.9, 1.1],
 [5.0, 3.4, 1.6, 0.4],
 [6.1, 3.0, 4.9, 1.8],
 [5.0, 3.3, 1.4, 0.2],
 [6.3, 3.3, 4.7, 1.6]]
firstTrainFeatures.shape: [32, 4]
First batch of labels: [1, 1, 0, 1, 2, 2, 0, 2, 1, 2, 0, 0, 0, 0, 0, 2, 2, 2, 0, 1, 0, 2, 0, 0, 2, 1, 2, 1, 0, 2, 0, 1]
firstTrainLabels.shape: [32]

Perhatikan bahwa fitur untuk pertama batchSize contoh dikelompokkan bersama-sama (atau batched) ke firstTrainFeatures , dan bahwa label untuk pertama batchSize contoh ditumpuk menjadi firstTrainLabels .

Anda dapat mulai melihat beberapa cluster dengan memplot beberapa fitur dari batch, menggunakan matplotlib Python:

let firstTrainFeaturesTransposed = firstTrainFeatures.transposed()
let petalLengths = firstTrainFeaturesTransposed[2].scalars
let sepalLengths = firstTrainFeaturesTransposed[0].scalars

plt.scatter(petalLengths, sepalLengths, c: firstTrainLabels.array.scalars)
plt.xlabel("Petal length")
plt.ylabel("Sepal length")
plt.show()

png

Use `print()` to show values.

Pilih jenis model

Mengapa model?

Model adalah hubungan antara fitur dan label. Untuk masalah klasifikasi iris mata, model mendefinisikan hubungan antara pengukuran sepal dan kelopak dan spesies iris yang diprediksi. Beberapa model sederhana dapat dijelaskan dengan beberapa baris aljabar, tetapi model pembelajaran mesin yang kompleks memiliki banyak parameter yang sulit untuk diringkas.

Bisakah Anda menentukan hubungan antara empat fitur dan spesies iris tanpa menggunakan pembelajaran mesin? Artinya, dapatkah Anda menggunakan teknik pemrograman tradisional (misalnya, banyak pernyataan bersyarat) untuk membuat model? Mungkin — jika Anda menganalisis kumpulan data cukup lama untuk menentukan hubungan antara pengukuran kelopak dan sepal dengan spesies tertentu. Dan ini menjadi sulit — mungkin tidak mungkin — pada kumpulan data yang lebih rumit. Pendekatan pembelajaran mesin yang baik menentukan model untuk Anda . Jika Anda memasukkan cukup banyak contoh yang representatif ke dalam jenis model pembelajaran mesin yang tepat, program akan mencari tahu hubungannya untuk Anda.

Pilih modelnya

Kita perlu memilih model yang akan dilatih. Ada banyak jenis model dan memilih yang bagus membutuhkan pengalaman. Tutorial ini menggunakan neural network untuk menyelesaikan masalah klasifikasi iris. Jaringan neural dapat menemukan hubungan yang kompleks antara fitur dan label. Ini adalah grafik yang sangat terstruktur, diatur menjadi satu atau lebih lapisan tersembunyi . Setiap lapisan tersembunyi terdiri dari satu atau lebih neuron . Ada beberapa kategori jaringan saraf dan program ini menggunakan jaringan saraf padat atau jaringan saraf yang terhubung sepenuhnya : neuron dalam satu lapisan menerima koneksi masukan dari setiap neuron di lapisan sebelumnya. Misalnya, Gambar 2 mengilustrasikan jaringan saraf padat yang terdiri dari lapisan masukan, dua lapisan tersembunyi, dan lapisan keluaran:

Diagram arsitektur jaringan: Input, 2 lapisan tersembunyi, dan keluaran
Gambar 2. Jaringan neural dengan fitur, lapisan tersembunyi, dan prediksi.

Saat model dari Gambar 2 dilatih dan diberi contoh tanpa label, model tersebut menghasilkan tiga prediksi: kemungkinan bahwa bunga ini merupakan spesies iris tertentu. Prediksi ini disebut inferensi . Untuk contoh ini, jumlah prediksi keluaran adalah 1.0. Pada Gambar 2, prediksi ini dibagi menjadi: 0.02 untuk Iris setosa , 0.95 untuk Iris versicolor , dan 0.03 untuk Iris virginica . Artinya, model tersebut memprediksi — dengan 95% probabilitas — bahwa contoh bunga yang tidak berlabel adalah Iris versicolor .

Buat model menggunakan Swift untuk TensorFlow Deep Learning Library

Swift untuk TensorFlow Deep Learning Library mendefinisikan lapisan primitif dan konvensi untuk menghubungkan keduanya, yang memudahkan pembuatan model dan eksperimen.

Model adalah struct yang sesuai dengan Layer , yang berarti ia mendefinisikan metode callAsFunction(_:) yang memetakan Tensor masukan ke Tensor keluaran. Metode callAsFunction(_:) sering hanya mengurutkan input melalui sublayer. Mari kita definisikan IrisModel yang mengurutkan input melalui tiga sublayer Dense .

import TensorFlow

let hiddenSize: Int = 10
struct IrisModel: Layer {
    var layer1 = Dense<Float>(inputSize: 4, outputSize: hiddenSize, activation: relu)
    var layer2 = Dense<Float>(inputSize: hiddenSize, outputSize: hiddenSize, activation: relu)
    var layer3 = Dense<Float>(inputSize: hiddenSize, outputSize: 3)

    @differentiable
    func callAsFunction(_ input: Tensor<Float>) -> Tensor<Float> {
        return input.sequenced(through: layer1, layer2, layer3)
    }
}

var model = IrisModel()

Fungsi aktivasi menentukan bentuk keluaran dari setiap node di lapisan. Non-linearitas ini penting — tanpanya model akan setara dengan satu lapisan. Ada banyak aktivasi yang tersedia, tetapi ULT biasa digunakan untuk lapisan tersembunyi.

Jumlah ideal hidden layer dan neuron bergantung pada masalah dan dataset. Seperti banyak aspek pembelajaran mesin, memilih bentuk terbaik jaringan neural membutuhkan campuran pengetahuan dan eksperimen. Sebagai aturan praktis, meningkatkan jumlah lapisan tersembunyi dan neuron biasanya menciptakan model yang lebih kuat, yang membutuhkan lebih banyak data untuk dilatih secara efektif.

Menggunakan model

Mari kita lihat sekilas apa yang dilakukan model ini pada sekumpulan fitur:

// Apply the model to a batch of features.
let firstTrainPredictions = model(firstTrainFeatures)
print(firstTrainPredictions[0..<5])
[[  1.1514063,  -0.7520321,  -0.6730235],
 [  1.4915676,  -0.9158071,  -0.9957161],
 [  1.0549936,  -0.7799266,   -0.410466],
 [  1.1725322, -0.69009197,  -0.8345413],
 [  1.4870572,  -0.8644099,  -1.0958937]]

Di sini, setiap contoh mengembalikan logit untuk setiap kelas.

Untuk mengonversi logit ini menjadi probabilitas untuk setiap kelas, gunakan fungsi softmax :

print(softmax(firstTrainPredictions[0..<5]))
[[  0.7631462,  0.11375094, 0.123102814],
 [  0.8523791, 0.076757915,  0.07086295],
 [  0.7191151,  0.11478964,  0.16609532],
 [ 0.77540654,  0.12039323,  0.10420021],
 [  0.8541314,  0.08133837, 0.064530246]]

Mengambil argmax di seluruh kelas memberi kita indeks kelas yang diprediksi. Tapi, modelnya belum dilatih, jadi ini bukan prediksi yang bagus.

print("Prediction: \(firstTrainPredictions.argmax(squeezingAxis: 1))")
print("    Labels: \(firstTrainLabels)")
Prediction: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
    Labels: [1, 1, 0, 1, 2, 2, 0, 2, 1, 2, 0, 0, 0, 0, 0, 2, 2, 2, 0, 1, 0, 2, 0, 0, 2, 1, 2, 1, 0, 2, 0, 1]

Latih modelnya

Pelatihan adalah tahap pembelajaran mesin ketika model dioptimalkan secara bertahap, atau model mempelajari kumpulan data. Tujuannya adalah untuk mempelajari cukup banyak tentang struktur set data pelatihan untuk membuat prediksi tentang data yang tidak terlihat. Jika Anda mempelajari terlalu banyak tentang set data pelatihan, prediksi hanya berfungsi untuk data yang telah dilihatnya dan tidak akan digeneralisasi. Masalah ini disebut overfitting — ini seperti menghafal jawaban alih-alih memahami bagaimana memecahkan masalah.

Masalah klasifikasi iris adalah contoh pembelajaran mesin yang diawasi : model dilatih dari contoh yang berisi label. Dalam pembelajaran mesin tanpa pengawasan , contoh tidak mengandung label. Sebaliknya, model biasanya menemukan pola di antara fitur.

Pilih fungsi kerugian

Baik tahap pelatihan maupun evaluasi perlu menghitung kerugian model. Ini mengukur seberapa jauh prediksi model berasal dari label yang diinginkan, dengan kata lain, seberapa buruk performa model. Kami ingin meminimalkan, atau mengoptimalkan, nilai ini.

Model kita akan menghitung kerugiannya menggunakan fungsi softmaxCrossEntropy(logits:labels:) yang mengambil prediksi probabilitas kelas model dan label yang diinginkan, dan mengembalikan kerugian rata-rata di seluruh contoh.

Mari menghitung kerugian untuk model yang tidak terlatih saat ini:

let untrainedLogits = model(firstTrainFeatures)
let untrainedLoss = softmaxCrossEntropy(logits: untrainedLogits, labels: firstTrainLabels)
print("Loss test: \(untrainedLoss)")
Loss test: 1.7598655

Buat pengoptimal

Pengoptimal menerapkan gradien yang dihitung ke variabel model untuk meminimalkan fungsi loss . Anda dapat menganggap fungsi kerugian sebagai permukaan lengkung (lihat Gambar 3) dan kami ingin menemukan titik terendahnya dengan berjalan-jalan. Gradien mengarah ke tanjakan paling curam — jadi kita akan melakukan perjalanan sebaliknya dan menuruni bukit. Dengan menghitung kerugian dan gradien secara berulang untuk setiap kelompok, kita akan menyesuaikan model selama pelatihan. Secara bertahap, model akan menemukan kombinasi bobot dan bias terbaik untuk meminimalkan kerugian. Dan semakin rendah kerugiannya, semakin baik prediksi modelnya.

Algoritme pengoptimalan divisualisasikan dari waktu ke waktu dalam ruang 3D.
Gambar 3. Algoritma pengoptimalan divisualisasikan dari waktu ke waktu dalam ruang 3D.
(Sumber: Stanford class CS231n , Lisensi MIT, Kredit gambar: Alec Radford )

Swift untuk TensorFlow memiliki banyak algoritme pengoptimalan yang tersedia untuk pelatihan. Model ini menggunakan pengoptimal SGD yang mengimplementasikan algoritmastochastic gradient descent (SGD). learningRate menetapkan ukuran langkah yang harus diambil untuk setiap iterasi menuruni bukit. Ini adalah hyperparameter yang biasanya akan Anda sesuaikan untuk mencapai hasil yang lebih baik.

let optimizer = SGD(for: model, learningRate: 0.01)

Mari gunakan optimizer untuk mengambil satu langkah penurunan gradien. Pertama, kami menghitung gradien kerugian sehubungan dengan model:

let (loss, grads) = valueWithGradient(at: model) { model -> Tensor<Float> in
    let logits = model(firstTrainFeatures)
    return softmaxCrossEntropy(logits: logits, labels: firstTrainLabels)
}
print("Current loss: \(loss)")
Current loss: 1.7598655

Selanjutnya, kami meneruskan gradien yang baru saja kami hitung ke pengoptimal, yang memperbarui variabel model yang dapat dibedakan sesuai:

optimizer.update(&model, along: grads)

Jika kita menghitung kerugian lagi, itu harus lebih kecil, karena langkah penurunan gradien (biasanya) mengurangi kerugian:

let logitsAfterOneStep = model(firstTrainFeatures)
let lossAfterOneStep = softmaxCrossEntropy(logits: logitsAfterOneStep, labels: firstTrainLabels)
print("Next loss: \(lossAfterOneStep)")
Next loss: 1.5318773

Loop pelatihan

Dengan semua bagian di tempatnya, model siap untuk pelatihan! Training loop memasukkan contoh set data ke dalam model untuk membantunya membuat prediksi yang lebih baik. Blok kode berikut menyiapkan langkah-langkah pelatihan ini:

  1. Iterasi setiap epoch . Epoch adalah salah satu jalur melalui dataset.
  2. Dalam satu epoch, lakukan iterasi pada setiap batch dalam epoch pelatihan
  3. Susun batch dan ambil fiturnya ( x ) dan label ( y ).
  4. Dengan menggunakan fitur kumpulan yang tersusun, buat prediksi dan bandingkan dengan label. Ukur ketidakakuratan prediksi dan gunakan itu untuk menghitung kerugian dan gradien model.
  5. Gunakan penurunan gradien untuk memperbarui variabel model.
  6. Lacak beberapa statistik untuk visualisasi.
  7. Ulangi untuk setiap periode.

Variabel epochCount adalah berapa kali mengulang kumpulan kumpulan data. Berlawanan dengan intuisi, melatih model lebih lama tidak menjamin model yang lebih baik. epochCount adalah hyperparameter yang dapat Anda epochCount . Memilih nomor yang tepat biasanya membutuhkan pengalaman dan eksperimen.

let epochCount = 500
var trainAccuracyResults: [Float] = []
var trainLossResults: [Float] = []
func accuracy(predictions: Tensor<Int32>, truths: Tensor<Int32>) -> Float {
    return Tensor<Float>(predictions .== truths).mean().scalarized()
}

for (epochIndex, epoch) in trainingEpochs.prefix(epochCount).enumerated() {
    var epochLoss: Float = 0
    var epochAccuracy: Float = 0
    var batchCount: Int = 0
    for batchSamples in epoch {
        let batch = batchSamples.collated
        let (loss, grad) = valueWithGradient(at: model) { (model: IrisModel) -> Tensor<Float> in
            let logits = model(batch.features)
            return softmaxCrossEntropy(logits: logits, labels: batch.labels)
        }
        optimizer.update(&model, along: grad)

        let logits = model(batch.features)
        epochAccuracy += accuracy(predictions: logits.argmax(squeezingAxis: 1), truths: batch.labels)
        epochLoss += loss.scalarized()
        batchCount += 1
    }
    epochAccuracy /= Float(batchCount)
    epochLoss /= Float(batchCount)
    trainAccuracyResults.append(epochAccuracy)
    trainLossResults.append(epochLoss)
    if epochIndex % 50 == 0 {
        print("Epoch \(epochIndex): Loss: \(epochLoss), Accuracy: \(epochAccuracy)")
    }
}
Epoch 0: Loss: 1.475254, Accuracy: 0.34375
Epoch 50: Loss: 0.91668004, Accuracy: 0.6458333
Epoch 100: Loss: 0.68662673, Accuracy: 0.6979167
Epoch 150: Loss: 0.540665, Accuracy: 0.6979167
Epoch 200: Loss: 0.46283028, Accuracy: 0.6979167
Epoch 250: Loss: 0.4134724, Accuracy: 0.8229167
Epoch 300: Loss: 0.35054502, Accuracy: 0.8958333
Epoch 350: Loss: 0.2731444, Accuracy: 0.9375
Epoch 400: Loss: 0.23622067, Accuracy: 0.96875
Epoch 450: Loss: 0.18956228, Accuracy: 0.96875

Visualisasikan fungsi kerugian dari waktu ke waktu

Meskipun mencetak kemajuan pelatihan model itu membantu, sering kali lebih membantu untuk melihat kemajuan ini. Kita dapat membuat grafik dasar menggunakan modul matplotlib Python.

Menafsirkan grafik ini membutuhkan pengalaman, tetapi Anda benar-benar ingin melihat kerugian turun dan akurasinya naik.

plt.figure(figsize: [12, 8])

let accuracyAxes = plt.subplot(2, 1, 1)
accuracyAxes.set_ylabel("Accuracy")
accuracyAxes.plot(trainAccuracyResults)

let lossAxes = plt.subplot(2, 1, 2)
lossAxes.set_ylabel("Loss")
lossAxes.set_xlabel("Epoch")
lossAxes.plot(trainLossResults)

plt.show()

png

Use `print()` to show values.

Perhatikan bahwa sumbu y pada grafik tidak berbasis nol.

Evaluasi efektivitas model

Setelah model dilatih, kita bisa mendapatkan beberapa statistik tentang performanya.

Mengevaluasi berarti menentukan seberapa efektif model membuat prediksi. Untuk menentukan keefektifan model pada klasifikasi iris, berikan beberapa pengukuran sepal dan kelopak ke model dan minta model untuk memprediksi spesies iris apa yang mereka wakili. Kemudian bandingkan prediksi model dengan label sebenarnya. Misalnya, model yang memilih spesies yang benar pada setengah contoh masukan memiliki akurasi 0.5 . Gambar 4 menunjukkan model yang sedikit lebih efektif, mendapatkan 4 dari 5 prediksi benar dengan akurasi 80%:

Fitur contoh Label Prediksi model
5.9 3.0 4.3 1.5 1 1
6.9 3.1 5.4 2.1 2 2
5.1 3.3 1.7 0,5 0 0
6.0 3.4 4.5 1.6 1 2
5.5 2.5 4.0 1.3 1 1
Gambar 4. Pengklasifikasi iris yang akurat 80%.

Siapkan set data pengujian

Mengevaluasi model sama dengan melatih model. Perbedaan terbesar adalah contoh berasal dari set pengujian terpisah dan bukan set pelatihan. Untuk menilai keefektifan model secara adil, contoh yang digunakan untuk mengevaluasi model harus berbeda dari contoh yang digunakan untuk melatih model.

Penyiapan untuk set data pengujian mirip dengan penyiapan untuk set data pelatihan. Unduh set pengujian dari http://download.tensorflow.org/data/iris_test.csv :

let testDataFilename = "iris_test.csv"
download(from: "http://download.tensorflow.org/data/iris_test.csv", to: testDataFilename)

Sekarang muat ke dalam array IrisBatch es:

let testDataset = loadIrisDatasetFromCSV(
    contentsOf: testDataFilename, hasHeader: true,
    featureColumns: [0, 1, 2, 3], labelColumns: [4]).inBatches(of: batchSize)

Evaluasi model pada set data pengujian

Berbeda dengan tahap pelatihan, model hanya mengevaluasi satu periode data pengujian. Di sel kode berikut, kami mengulangi setiap contoh dalam set pengujian dan membandingkan prediksi model dengan label sebenarnya. Ini digunakan untuk mengukur akurasi model di seluruh set pengujian.

// NOTE: Only a single batch will run in the loop since the batchSize we're using is larger than the test set size
for batchSamples in testDataset {
    let batch = batchSamples.collated
    let logits = model(batch.features)
    let predictions = logits.argmax(squeezingAxis: 1)
    print("Test batch accuracy: \(accuracy(predictions: predictions, truths: batch.labels))")
}
Test batch accuracy: 0.96666664

Kita bisa lihat pada batch pertama, misalnya modelnya biasanya benar:

let firstTestBatch = testDataset.first!.collated
let firstTestBatchLogits = model(firstTestBatch.features)
let firstTestBatchPredictions = firstTestBatchLogits.argmax(squeezingAxis: 1)

print(firstTestBatchPredictions)
print(firstTestBatch.labels)
[1, 2, 0, 1, 1, 1, 0, 2, 1, 2, 2, 0, 2, 1, 1, 0, 1, 0, 0, 2, 0, 1, 2, 2, 1, 1, 0, 1, 2, 1]
[1, 2, 0, 1, 1, 1, 0, 2, 1, 2, 2, 0, 2, 1, 1, 0, 1, 0, 0, 2, 0, 1, 2, 1, 1, 1, 0, 1, 2, 1]

Gunakan model terlatih untuk membuat prediksi

Kami telah melatih model dan mendemonstrasikan bahwa itu bagus — tetapi tidak sempurna — dalam mengklasifikasikan spesies iris. Sekarang mari gunakan model terlatih untuk membuat beberapa prediksi pada contoh tak berlabel ; yaitu, pada contoh yang berisi fitur tetapi bukan label.

Dalam kehidupan nyata, contoh tak berlabel dapat berasal dari banyak sumber berbeda termasuk aplikasi, file CSV, dan data feed. Untuk saat ini, kami akan memberikan tiga contoh tak berlabel secara manual untuk memprediksi labelnya. Ingat, nomor label dipetakan ke representasi bernama sebagai:

  • 0 : Iris setosa
  • 1 : Iris versicolor
  • 2 : Iris virginica
let unlabeledDataset: Tensor<Float> =
    [[5.1, 3.3, 1.7, 0.5],
     [5.9, 3.0, 4.2, 1.5],
     [6.9, 3.1, 5.4, 2.1]]

let unlabeledDatasetPredictions = model(unlabeledDataset)

for i in 0..<unlabeledDatasetPredictions.shape[0] {
    let logits = unlabeledDatasetPredictions[i]
    let classIdx = logits.argmax().scalar!
    print("Example \(i) prediction: \(classNames[Int(classIdx)]) (\(softmax(logits)))")
}
Example 0 prediction: Iris setosa ([   0.98731947,   0.012679046, 1.4035809e-06])
Example 1 prediction: Iris versicolor ([0.005065103,  0.85957265,  0.13536224])
Example 2 prediction: Iris virginica ([2.9613977e-05,     0.2637373,    0.73623306])