Model eğitimi adım adım

TensorFlow.org'da görüntüleyin Google Colab'da çalıştırın Kaynağı GitHub'da görüntüleyin

Bu kılavuz, iris çiçeklerini türlere göre kategorize eden bir makine öğrenimi modeli oluşturarak TensorFlow için Swift'i tanıtıyor. TensorFlow için Swift kullanır:

  1. Bir model yapmak,
  2. Bu modeli örnek veriler üzerinde eğitin ve
  3. Bilinmeyen veriler hakkında tahminler yapmak için modeli kullanın.

TensorFlow programlama

Bu kılavuz, şu üst düzey Swift for TensorFlow kavramlarını kullanır:

  • Epochs API ile verileri içe aktarın.
  • Swift soyutlamalarını kullanarak modeller oluşturun.
  • Saf Swift kitaplıkları mevcut olmadığında Swift'in Python birlikte çalışabilirliğini kullanarak Python kitaplıklarını kullanın.

Bu öğretici, birçok TensorFlow programı gibi yapılandırılmıştır:

  1. Veri kümelerini içe aktarın ve ayrıştırın.
  2. Modelin türünü seçin.
  3. Modeli eğitin.
  4. Modelin etkinliğini değerlendirin.
  5. Tahminlerde bulunmak için eğitilmiş modeli kullanın.

Kurulum programı

İçe aktarmayı yapılandır

TensorFlow ve bazı kullanışlı Python modüllerini içe aktarın.

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)
}

iris sınıflandırma sorunu

Bulduğunuz her iris çiçeğini kategorize etmenin otomatik bir yolunu arayan bir botanikçi olduğunuzu hayal edin. Makine öğrenimi, çiçekleri istatistiksel olarak sınıflandırmak için birçok algoritma sağlar. Örneğin, gelişmiş bir makine öğrenimi programı, çiçekleri fotoğraflara göre sınıflandırabilir. Hırslarımız daha mütevazı - iris çiçeklerini çanak yapraklarının ve taç yapraklarının uzunluk ve genişlik ölçümlerine göre sınıflandıracağız.

Iris cinsi yaklaşık 300 tür içerir, ancak programımız yalnızca aşağıdaki üçünü sınıflandıracaktır:

  • iris setozası
  • iris virginica
  • iris çok renkli
Üç iris türü için karşılaştırıldığında petal geometrisi: Iris setosa, Iris virginica ve Iris versicolor
Şekil 1. İris setosa ( Radomil , CC BY-SA 3.0 tarafından), Iris versicolor , ( Dlanglois , CC BY-SA 3.0 tarafından) ve Iris virginica ( Frank Mayfield tarafından, CC BY-SA 2.0).

Neyse ki, birisi çanak yaprağı ve taç yaprağı ölçümleriyle 120 iris çiçeğinden oluşan bir veri seti oluşturmuştur . Bu, yeni başlayan makine öğrenimi sınıflandırma sorunları için popüler olan klasik bir veri kümesidir.

Eğitim veri kümesini içe aktarın ve ayrıştırın

Veri kümesi dosyasını indirin ve bu Swift programı tarafından kullanılabilecek bir yapıya dönüştürün.

Veri kümesini indirin

Eğitim veri seti dosyasını http://download.tensorflow.org/data/iris_training.csv adresinden indirin.

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

Verileri inceleyin

Bu veri kümesi, iris_training.csv , virgülle ayrılmış değerler (CSV) olarak biçimlendirilmiş tablo verilerini depolayan bir düz metin dosyasıdır. İlk 5 girişe bakalım.

let f = Python.open(trainDataFilename)
for _ in 0..<5 {
    print(Python.next(f).strip())
}
print(f.close())
tutucu7 l10n-yer
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

Veri kümesinin bu görünümünden aşağıdakilere dikkat edin:

  1. İlk satır, veri kümesi hakkında bilgi içeren bir başlıktır:
    • Toplam 120 örnek var. Her örneğin dört özelliği ve üç olası etiket adından biri vardır.
  2. Sonraki satırlar, her satıra bir örnek olacak şekilde veri kayıtlarıdır, burada:
    • İlk dört alan özelliklerdir : bunlar bir örneğin özellikleridir. Burada alanlar, çiçek ölçümlerini temsil eden kayan sayıları tutar.
    • Son sütun etikettir : bu, tahmin etmek istediğimiz değerdir. Bu veri kümesi için bir çiçek adına karşılık gelen 0, 1 veya 2 tamsayı değeridir.

Bunu kod halinde yazalım:

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

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

Her etiket, dize adıyla ilişkilendirilir (örneğin, "setosa"), ancak makine öğrenimi tipik olarak sayısal değerlere dayanır. Etiket numaraları, aşağıdakiler gibi adlandırılmış bir temsile eşlenir:

  • 0 : İris setozası
  • 1 : İris çok renkli
  • 2 : İris virginica

Özellikler ve etiketler hakkında daha fazla bilgi için Machine Learning Crash Course'un ML Terminolojisi bölümüne bakın .

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

Epochs API'sini kullanarak bir veri kümesi oluşturun

Swift for TensorFlow'un Epochs API'si, verileri okumak ve bunları eğitim için kullanılan bir forma dönüştürmek için kullanılan üst düzey bir API'dir.

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})
    }
}

İndirdiğimiz veri setleri CSV formatında olduğu için IrisBatch nesnelerinin bir listesi olarak verileri yüklemek için bir fonksiyon yazalım.

/// 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)}

    }

Artık eğitim veri kümesini yüklemek ve bir TrainingEpochs nesnesi oluşturmak için CSV yükleme işlevini kullanabiliriz.

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

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

TrainingEpochs nesnesi, sonsuz bir dönem dizisidir. Her dönem, IrisBatch es içerir. İlk çağın ilk unsuruna bakalım.

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)")
tutucu15 l10n-yer
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]

İlk batchSize örneklerinin özelliklerinin firstTrainFeatures içinde gruplandırıldığına (veya firstTrainFeatures ) ve ilk batchSize örneklerine ait etiketlerin batchSize içinde firstTrainLabels .

Python'un matplotlib'ini kullanarak toplu işten birkaç özelliği çizerek bazı kümeleri görmeye başlayabilirsiniz:

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.

Modelin türünü seçin

Neden modeli?

Model , özellikler ve etiket arasındaki ilişkidir. İris sınıflandırma problemi için model, çanak yaprağı ve taç yaprağı ölçümleri ile tahmin edilen iris türleri arasındaki ilişkiyi tanımlar. Bazı basit modeller birkaç satır cebir ile açıklanabilir, ancak karmaşık makine öğrenimi modellerinin özetlemesi zor olan çok sayıda parametresi vardır.

Dört özellik ile iris türleri arasındaki ilişkiyi makine öğrenimini kullanmadan belirleyebilir misiniz? Yani, bir model oluşturmak için geleneksel programlama tekniklerini (örneğin, birçok koşullu ifadeyi) kullanabilir misiniz? Belki de veri setini belirli bir türün taç yaprağı ve çanak yaprağı ölçümleri arasındaki ilişkileri belirlemeye yetecek kadar uzun süre analiz ettiyseniz. Ve bu, daha karmaşık veri kümelerinde zor, hatta imkansız hale gelir. İyi bir makine öğrenimi yaklaşımı sizin için modeli belirler . Yeterli temsili örneği doğru makine öğrenimi modeli türüne beslerseniz, program ilişkileri sizin için çözecektir.

modeli seçin

Eğitmek için model türünü seçmemiz gerekiyor. Birçok model çeşidi vardır ve iyi bir model seçmek tecrübe ister. Bu öğretici, iris sınıflandırma problemini çözmek için bir sinir ağı kullanır. Sinir ağları , özellikler ve etiket arasında karmaşık ilişkiler bulabilir. Bir veya daha fazla gizli katman halinde düzenlenmiş, yüksek düzeyde yapılandırılmış bir grafiktir. Her gizli katman bir veya daha fazla nörondan oluşur. Sinir ağlarının birkaç kategorisi vardır ve bu program yoğun veya tam bağlantılı bir sinir ağı kullanır: bir katmandaki nöronlar, önceki katmandaki her nörondan girdi bağlantıları alır. Örneğin, Şekil 2 bir girdi katmanı, iki gizli katman ve bir çıktı katmanından oluşan yoğun bir sinir ağını göstermektedir:

Ağ mimarisinin bir diyagramı: Girişler, 2 gizli katman ve çıkışlar
Şekil 2. Özellikleri, gizli katmanları ve tahminleri olan bir sinir ağı.

Şekil 2'deki model eğitildiğinde ve etiketlenmemiş bir örnekle beslendiğinde, üç tahmin verir: Bu çiçeğin verilen iris türü olma olasılığı. Bu tahmine çıkarım denir. Bu örnek için, çıktı tahminlerinin toplamı 1.0'dır. Şekil 2'de bu tahmin şu şekildedir: İris setosa için 0.02 , İris versicolor için 0.95 ve İris virginica için 0.03 . Bu, modelin %95 olasılıkla, etiketlenmemiş bir örnek çiçeğin bir İris versicolor olduğunu tahmin ettiği anlamına gelir.

TensorFlow Derin Öğrenme Kitaplığı için Swift kullanarak bir model oluşturun

Swift for TensorFlow Derin Öğrenme Kitaplığı , bunları birbirine bağlamak için ilkel katmanları ve kuralları tanımlar, bu da model oluşturmayı ve denemeyi kolaylaştırır.

Model, Layer ile uyumlu bir yapıdır; bu, Tensor s girişini Tensor s çıkışına eşleyen bir struct callAsFunction(_:) yöntemini tanımladığı anlamına gelir. callAsFunction(_:) yöntemi genellikle girdiyi alt katmanlar aracılığıyla sıralar. Girdiyi üç Dense alt katman aracılığıyla sıralayan bir IrisModel tanımlayalım.

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()

Aktivasyon işlevi, katmandaki her bir düğümün çıktı şeklini belirler. Bu doğrusal olmama durumları önemlidir - onlar olmadan model tek bir katmana eşdeğer olacaktır. Kullanılabilir birçok etkinleştirme vardır, ancak ReLU gizli katmanlar için ortaktır.

İdeal gizli katman ve nöron sayısı, soruna ve veri kümesine bağlıdır. Makine öğreniminin birçok yönü gibi, sinir ağının en iyi şeklini seçmek de bilgi ve deney karışımı gerektirir. Genel bir kural olarak, gizli katmanların ve nöronların sayısını artırmak tipik olarak daha güçlü bir model oluşturur ve bu da etkili bir şekilde eğitmek için daha fazla veri gerektirir.

modeli kullanma

Bu modelin bir dizi özelliğe ne yaptığına hızlıca bir göz atalım:

// Apply the model to a batch of features.
let firstTrainPredictions = model(firstTrainFeatures)
print(firstTrainPredictions[0..<5])
tutucu20 l10n-yer
[[  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]]

Burada her örnek, her sınıf için bir logit döndürür.

Bu logitleri her sınıf için bir olasılığa dönüştürmek için softmax işlevini kullanın:

print(softmax(firstTrainPredictions[0..<5]))
tutucu22 l10n-yer
[[  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]]

argmax sınıflar arasında almak bize tahmin edilen sınıf indeksini verir. Ancak model henüz eğitilmedi, bu yüzden bunlar iyi tahminler değil.

print("Prediction: \(firstTrainPredictions.argmax(squeezingAxis: 1))")
print("    Labels: \(firstTrainLabels)")
tutucu24 l10n-yer
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]

Modeli eğit

Eğitim , model kademeli olarak optimize edildiğinde veya model veri kümesini öğrendiğinde makine öğreniminin aşamasıdır. Amaç, görünmeyen veriler hakkında tahminler yapmak için eğitim veri kümesinin yapısı hakkında yeterince bilgi edinmektir. Eğitim veri kümesi hakkında çok fazla şey öğrenirseniz, tahminler yalnızca gördüğü veriler için çalışır ve genelleştirilemez. Bu soruna fazla uydurma denir - bir sorunun nasıl çözüleceğini anlamak yerine cevapları ezberlemek gibidir.

İris sınıflandırma sorunu, denetimli makine öğreniminin bir örneğidir: model, etiketler içeren örneklerden eğitilmiştir. Denetimsiz makine öğreniminde örnekler etiket içermez. Bunun yerine, model tipik olarak özellikler arasında desenler bulur.

Bir kayıp işlevi seçin

Hem eğitim hem de değerlendirme aşamalarının modelin kaybını hesaplaması gerekir. Bu, bir modelin tahminlerinin istenen etiketten ne kadar uzak olduğunu, başka bir deyişle modelin ne kadar kötü performans gösterdiğini ölçer. Bu değeri en aza indirmek veya optimize etmek istiyoruz.

Modelimiz, modelin sınıf olasılık tahminlerini ve istenen etiketi alan softmaxCrossEntropy(logits:labels:) işlevini kullanarak kaybını hesaplayacak ve örnekler arasında ortalama kaybı döndürecektir.

Mevcut eğitimsiz model için kaybı hesaplayalım:

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

Optimize edici oluşturun

Bir optimize edici, loss fonksiyonunu en aza indirmek için hesaplanan gradyanları modelin değişkenlerine uygular. Kayıp fonksiyonunu eğri bir yüzey olarak düşünebilirsiniz (bkz. Şekil 3) ve biz onun en alt noktasını etrafta dolaşarak bulmak istiyoruz. Eğimler en dik çıkış yönünü gösteriyor - bu yüzden ters yöne gideceğiz ve tepeden aşağı ineceğiz. Her parti için kayıp ve gradyanı yinelemeli olarak hesaplayarak, eğitim sırasında modeli ayarlayacağız. Yavaş yavaş, model, kaybı en aza indirmek için en iyi ağırlık ve sapma kombinasyonunu bulacaktır. Ve kayıp ne kadar düşükse, modelin tahminleri o kadar iyi olur.

Optimizasyon algoritmaları zaman içinde 3B uzayda görselleştirilir.
Şekil 3. 3B uzayda zaman içinde görselleştirilen optimizasyon algoritmaları.
(Kaynak: Stanford class CS231n , MIT Lisansı, Resim kredisi: Alec Radford )

Swift for TensorFlow, eğitim için kullanılabilecek birçok optimizasyon algoritmasına sahiptir. Bu model, stokastik gradyan iniş (SGD) algoritmasını uygulayan SGD optimizer'ı kullanır. learningRate , tepeden aşağı her yineleme için atılacak adım boyutunu ayarlar. Bu, daha iyi sonuçlar elde etmek için genellikle ayarlayacağınız bir hiperparametredir .

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

Tek bir eğimli iniş adımı atmak için optimizer ediciyi kullanalım. İlk olarak, modele göre kaybın gradyanını hesaplıyoruz:

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

Ardından, modelin türevlenebilir değişkenlerini buna göre güncelleyen optimize ediciye az önce hesapladığımız gradyanı iletiyoruz:

optimizer.update(&model, along: grads)

Kaybı tekrar hesaplarsak, daha küçük olmalıdır, çünkü gradyan iniş adımları (genellikle) kaybı azaltır:

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

Eğitim döngüsü

Tüm parçalar yerine oturduğunda, model eğitime hazır! Bir eğitim döngüsü, daha iyi tahminler yapmasına yardımcı olmak için veri kümesi örneklerini modele besler. Aşağıdaki kod bloğu, bu eğitim adımlarını ayarlar:

  1. Her çağda yineleyin. Bir dönem, veri kümesinden bir geçiştir.
  2. Bir çağda, eğitim çağındaki her grup üzerinde yineleme yapın
  3. Partiyi harmanlayın ve özelliklerini ( x ) ve etiketleyin ( y ).
  4. Harmanlanmış partinin özelliklerini kullanarak bir tahmin yapın ve bunu etiketle karşılaştırın. Tahminin yanlışlığını ölçün ve bunu modelin kaybını ve eğimlerini hesaplamak için kullanın.
  5. Modelin değişkenlerini güncellemek için gradyan inişini kullanın.
  6. Görselleştirme için bazı istatistikleri takip edin.
  7. Her dönem için tekrarlayın.

epochCount değişkeni, veri kümesi koleksiyonu üzerinde yapılacak döngü sayısıdır. Sezgisel olarak, bir modeli daha uzun süre eğitmek daha iyi bir modeli garanti etmez. epochCount , ayarlayabileceğiniz bir hiper parametredir . Doğru numarayı seçmek genellikle hem deneyim hem de deneme gerektirir.

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)")
    }
}
-yer tutucu35 l10n-yer
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

Zaman içinde kayıp işlevini görselleştirin

Modelin eğitim ilerlemesini yazdırmak yararlı olsa da, bu ilerlemeyi görmek genellikle daha yararlıdır. Python'un matplotlib modülünü kullanarak temel grafikler oluşturabiliriz.

Bu çizelgeleri yorumlamak biraz deneyim gerektirir, ancak gerçekten kaybın azaldığını ve doğruluğun arttığını görmek istersiniz.

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.

Grafiklerin y eksenlerinin sıfır tabanlı olmadığına dikkat edin.

Modelin etkinliğini değerlendirin

Artık model eğitildiğine göre, performansı hakkında bazı istatistikler elde edebiliriz.

Değerlendirme , modelin ne kadar etkili tahminler yaptığını belirlemek anlamına gelir. Modelin iris sınıflandırmasındaki etkinliğini belirlemek için, bazı sepal ve petal ölçümlerini modele iletin ve modelden hangi iris türlerini temsil ettiklerini tahmin etmesini isteyin. Ardından modelin tahminini gerçek etiketle karşılaştırın. Örneğin, girdi örneklerinin yarısında doğru türü seçen bir modelin doğruluğu 0.5 . Şekil 4, 5 tahminden 4'ünü %80 doğrulukla doğru yapan biraz daha etkili bir modeli göstermektedir:

Örnek özellikler Etiket Model tahmini
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
Şekil 4. %80 doğru olan bir iris sınıflandırıcı.

Test veri kümesini ayarlayın

Modeli değerlendirmek, modeli eğitmeye benzer. En büyük fark, örneklerin eğitim setinden ziyade ayrı bir test setinden gelmesidir. Bir modelin etkinliğini adil bir şekilde değerlendirmek için, bir modeli değerlendirmek için kullanılan örnekler, modeli eğitmek için kullanılan örneklerden farklı olmalıdır.

Test veri seti kurulumu, eğitim veri seti kurulumuna benzer. Test setini http://download.tensorflow.org/data/iris_test.csv adresinden indirin:

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

Şimdi onu bir dizi IrisBatch :

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

Modeli test veri setinde değerlendirin

Eğitim aşamasından farklı olarak model, test verilerinin yalnızca tek bir dönemini değerlendirir. Aşağıdaki kod hücresinde, test setindeki her örnek üzerinde yinelenir ve modelin tahminini gerçek etiketle karşılaştırırız. Bu, tüm test seti boyunca modelin doğruluğunu ölçmek için kullanılır.

// 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))")
}
tutucu41 l10n-yer
Test batch accuracy: 0.96666664

İlk partide görebiliriz, örneğin model genellikle doğrudur:

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

print(firstTestBatchPredictions)
print(firstTestBatch.labels)
tutucu43 l10n-yer
[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]

Tahmin yapmak için eğitilmiş modeli kullanın

Bir model eğittik ve bunun iris türlerini sınıflandırmada iyi olduğunu ama mükemmel olmadığını gösterdik. Şimdi etiketlenmemiş örnekler üzerinde bazı tahminler yapmak için eğitilmiş modeli kullanalım; yani, özellikler içeren ancak etiket içermeyen örneklerde.

Gerçek hayatta, etiketlenmemiş örnekler uygulamalar, CSV dosyaları ve veri akışları dahil olmak üzere birçok farklı kaynaktan gelebilir. Şimdilik, etiketlerini tahmin etmek için manuel olarak üç etiketlenmemiş örnek sağlayacağız. Hatırlayın, etiket numaraları şu şekilde adlandırılmış bir temsile eşlenir:

  • 0 : İris setozası
  • 1 : İris çok renkli
  • 2 : İris 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)))")
}
tutucu45 l10n-yer
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])