मॉडल प्रशिक्षण पूर्वाभ्यास

TensorFlow.org पर देखें Google Colab में चलाएं GitHub पर स्रोत देखें

यह मार्गदर्शिका एक मशीन लर्निंग मॉडल बनाकर TensorFlow के लिए स्विफ्ट का परिचय देती है जो प्रजातियों के अनुसार परितारिका के फूलों को वर्गीकृत करती है। यह TensorFlow के लिए स्विफ्ट का उपयोग करता है:

  1. मॉडल बनाना,
  2. उदाहरण डेटा पर इस मॉडल को प्रशिक्षित करें, और
  3. अज्ञात डेटा के बारे में भविष्यवाणियां करने के लिए मॉडल का उपयोग करें।

टेंसरफ्लो प्रोग्रामिंग

यह मार्गदर्शिका TensorFlow अवधारणाओं के लिए इन उच्च-स्तरीय स्विफ्ट का उपयोग करती है:

  • युग एपीआई के साथ डेटा आयात करें।
  • स्विफ्ट एब्स्ट्रैक्शन का उपयोग करके मॉडल बनाएं।
  • जब शुद्ध स्विफ्ट लाइब्रेरी उपलब्ध न हो तो स्विफ्ट के पायथन इंटरऑपरेबिलिटी का उपयोग करके पायथन लाइब्रेरी का उपयोग करें।

यह ट्यूटोरियल कई TensorFlow कार्यक्रमों की तरह संरचित है:

  1. डेटा सेट आयात और पार्स करें।
  2. मॉडल के प्रकार का चयन करें।
  3. मॉडल को प्रशिक्षित करें।
  4. मॉडल की प्रभावशीलता का मूल्यांकन करें।
  5. भविष्यवाणी करने के लिए प्रशिक्षित मॉडल का उपयोग करें।

सेटअप कार्यक्रम

आयात कॉन्फ़िगर करें

TensorFlow और कुछ उपयोगी पायथन मॉड्यूल आयात करें।

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

आईरिस वर्गीकरण समस्या

कल्पना कीजिए कि आप एक वनस्पति विज्ञानी हैं जो आपके द्वारा खोजे गए प्रत्येक आईरिस फूल को वर्गीकृत करने के लिए एक स्वचालित तरीका ढूंढ रहे हैं। मशीन लर्निंग फूलों को सांख्यिकीय रूप से वर्गीकृत करने के लिए कई एल्गोरिदम प्रदान करता है। उदाहरण के लिए, एक परिष्कृत मशीन लर्निंग प्रोग्राम तस्वीरों के आधार पर फूलों को वर्गीकृत कर सकता है। हमारी महत्वाकांक्षाएं अधिक विनम्र हैं - हम आईरिस के फूलों को उनके बाह्यदलों और पंखुड़ियों की लंबाई और चौड़ाई के माप के आधार पर वर्गीकृत करने जा रहे हैं।

आईरिस जीनस में लगभग 300 प्रजातियां शामिल हैं, लेकिन हमारा कार्यक्रम केवल निम्नलिखित तीन को वर्गीकृत करेगा:

  • आइरिस सेटोसा
  • आइरिस वर्जिनिका
  • आईरिस वर्सिकलर
तीन आईरिस प्रजातियों की तुलना में पेटल ज्यामिति: आईरिस सेटोसा, आईरिस वर्जिनिका, और आईरिस वर्सीकोलर
चित्र 1. आइरिस सेटोसा ( रेडोमिल द्वारा, सीसी बाय-एसए 3.0 द्वारा), आइरिस वर्सीकलर, ( डालंग्लॉइस द्वारा, सीसी बाय-एसए 3.0), और आइरिस वर्जिनिका ( फ्रैंक मेफील्ड द्वारा, सीसी बाय-एसए 2.0)।

सौभाग्य से, किसी ने पहले से ही सीपल और पंखुड़ी माप के साथ 120 आईरिस फूलों का डेटा सेट बनाया है। यह एक क्लासिक डेटासेट है जो शुरुआती मशीन लर्निंग वर्गीकरण समस्याओं के लिए लोकप्रिय है।

प्रशिक्षण डेटासेट आयात और पार्स करें

डेटासेट फ़ाइल डाउनलोड करें और इसे एक संरचना में परिवर्तित करें जिसका उपयोग इस स्विफ्ट प्रोग्राम द्वारा किया जा सकता है।

डेटासेट डाउनलोड करें

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)

डेटा का निरीक्षण करें

यह डेटासेट, iris_training.csv , एक सादा पाठ फ़ाइल है जो सारणीबद्ध डेटा को अल्पविराम से अलग किए गए मानों (CSV) के रूप में स्वरूपित करता है। आइए पहली 5 प्रविष्टियों को देखें।

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

डेटासेट के इस दृश्य से, निम्नलिखित पर ध्यान दें:

  1. पहली पंक्ति एक हेडर है जिसमें डेटासेट के बारे में जानकारी होती है:
    • कुल 120 उदाहरण हैं। प्रत्येक उदाहरण में चार विशेषताएं हैं और तीन संभावित लेबल नामों में से एक है।
  2. बाद की पंक्तियाँ डेटा रिकॉर्ड हैं, प्रति पंक्ति एक उदाहरण , जहाँ:
    • पहले चार क्षेत्र विशेषताएँ हैं: ये एक उदाहरण की विशेषताएँ हैं। यहां, खेतों में फूलों की माप का प्रतिनिधित्व करने वाले फ्लोट नंबर होते हैं।
    • अंतिम कॉलम लेबल है: यह वह मान है जिसकी हम भविष्यवाणी करना चाहते हैं। इस डेटासेट के लिए, यह 0, 1, या 2 का पूर्णांक मान है जो एक फूल के नाम से मेल खाता है।

आइए इसे कोड में लिखें:

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

प्रत्येक लेबल स्ट्रिंग नाम से जुड़ा होता है (उदाहरण के लिए, "सेटोसा"), लेकिन मशीन लर्निंग आमतौर पर संख्यात्मक मानों पर निर्भर करता है। लेबल नंबर एक नामित प्रतिनिधित्व के लिए मैप किए जाते हैं, जैसे:

  • 0 : आइरिस सेटोसा
  • 1 : आईरिस वर्सिकलर
  • 2 : आईरिस वर्जिनिका

सुविधाओं और लेबल के बारे में अधिक जानकारी के लिए, मशीन लर्निंग क्रैश कोर्स का एमएल शब्दावली अनुभाग देखें।

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

एपोच एपीआई का उपयोग करके डेटासेट बनाएं

TensorFlow के युग एपीआई के लिए स्विफ्ट डेटा पढ़ने और इसे प्रशिक्षण के लिए उपयोग किए जाने वाले रूप में बदलने के लिए एक उच्च-स्तरीय एपीआई है।

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

चूंकि हमारे द्वारा डाउनलोड किए गए डेटासेट सीएसवी प्रारूप में हैं, आइए डेटा में लोड करने के लिए आईरिसबैच ऑब्जेक्ट्स की सूची के रूप में एक फ़ंक्शन लिखें

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

    }

अब हम प्रशिक्षण डेटासेट को लोड करने और एक TrainingEpochs वस्तु बनाने के लिए CSV लोडिंग फ़ंक्शन का उपयोग कर सकते हैं

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

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

TrainingEpochs युग वस्तु युगों का एक अनंत क्रम है। प्रत्येक युग में IrisBatch es होता है। आइए पहले युग के पहले तत्व को देखें।

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]

ध्यान दें कि पहले batchSize उदाहरणों के लिए सुविधाओं को एक साथ (या बैच ) firstTrainFeatures में समूहीकृत किया जाता है, और यह कि पहले batchSize उदाहरणों के लिए लेबल firstTrainLabels में बैच किए जाते हैं।

आप पायथन के matplotlib का उपयोग करके बैच से कुछ सुविधाओं को प्लॉट करके कुछ क्लस्टर देखना शुरू कर सकते हैं:

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

पीएनजी

Use `print()` to show values.

मॉडल के प्रकार का चयन करें

मॉडल क्यों?

एक मॉडल सुविधाओं और लेबल के बीच का संबंध है। आईरिस वर्गीकरण समस्या के लिए, मॉडल सेपल और पंखुड़ी माप और अनुमानित आईरिस प्रजातियों के बीच संबंध को परिभाषित करता है। कुछ सरल मॉडल को बीजगणित की कुछ पंक्तियों के साथ वर्णित किया जा सकता है, लेकिन जटिल मशीन लर्निंग मॉडल में बड़ी संख्या में पैरामीटर होते हैं जिन्हें संक्षेप में प्रस्तुत करना मुश्किल होता है।

क्या आप मशीन लर्निंग का उपयोग किए बिना चार विशेषताओं और परितारिका प्रजातियों के बीच संबंध निर्धारित कर सकते हैं? यानी, क्या आप एक मॉडल बनाने के लिए पारंपरिक प्रोग्रामिंग तकनीकों (उदाहरण के लिए, बहुत सारे सशर्त बयान) का उपयोग कर सकते हैं? शायद — यदि आपने किसी विशेष प्रजाति के लिए पंखुड़ी और बाह्यदल माप के बीच संबंधों को निर्धारित करने के लिए डेटासेट का लंबे समय तक विश्लेषण किया है। और अधिक जटिल डेटासेट पर यह मुश्किल-शायद असंभव-हो जाता है। एक अच्छा मशीन लर्निंग दृष्टिकोण आपके लिए मॉडल निर्धारित करता है । यदि आप पर्याप्त प्रतिनिधि उदाहरणों को सही मशीन लर्निंग मॉडल प्रकार में फीड करते हैं, तो प्रोग्राम आपके लिए संबंधों का पता लगाएगा।

मॉडल का चयन करें

हमें प्रशिक्षित करने के लिए मॉडल के प्रकार का चयन करने की आवश्यकता है। कई प्रकार के मॉडल हैं और एक अच्छा चुनने का अनुभव होता है। यह ट्यूटोरियल आईरिस वर्गीकरण समस्या को हल करने के लिए एक तंत्रिका नेटवर्क का उपयोग करता है। तंत्रिका नेटवर्क सुविधाओं और लेबल के बीच जटिल संबंध ढूंढ सकते हैं। यह एक अत्यधिक संरचित ग्राफ है, जो एक या अधिक छिपी हुई परतों में व्यवस्थित होता है। प्रत्येक छिपी हुई परत में एक या अधिक न्यूरॉन्स होते हैं। तंत्रिका नेटवर्क की कई श्रेणियां हैं और यह प्रोग्राम घने, या पूरी तरह से जुड़े तंत्रिका नेटवर्क का उपयोग करता है: एक परत में न्यूरॉन्स पिछली परत में प्रत्येक न्यूरॉन से इनपुट कनेक्शन प्राप्त करते हैं। उदाहरण के लिए, चित्र 2 एक घने तंत्रिका नेटवर्क को दिखाता है जिसमें एक इनपुट परत, दो छिपी हुई परतें और एक आउटपुट परत होती है:

नेटवर्क आर्किटेक्चर का आरेख: इनपुट, 2 छिपी हुई परतें, और आउटपुट
चित्रा 2. सुविधाओं, छिपी परतों और भविष्यवाणियों के साथ एक तंत्रिका नेटवर्क।

जब चित्र 2 के मॉडल को प्रशिक्षित किया जाता है और एक बिना लेबल वाला उदाहरण दिया जाता है, तो यह तीन भविष्यवाणियां देता है: संभावना है कि यह फूल दी गई आईरिस प्रजाति है। इस भविष्यवाणी को अनुमान कहा जाता है। इस उदाहरण के लिए, आउटपुट पूर्वानुमानों का योग 1.0 है। चित्रा 2 में, यह भविष्यवाणी इस प्रकार टूटती है: आईरिस सेटोसा के लिए 0.02 , आईरिस वर्सिकलर के लिए 0.95 , और आईरिस वर्जिनिका के लिए 0.03 । इसका मतलब यह है कि मॉडल भविष्यवाणी करता है - 95% संभावना के साथ - कि एक लेबल रहित उदाहरण फूल एक आईरिस वर्सिकलर है।

TensorFlow डीप लर्निंग लाइब्रेरी के लिए स्विफ्ट का उपयोग करके एक मॉडल बनाएं

TensorFlow डीप लर्निंग लाइब्रेरी के लिए स्विफ्ट उन्हें एक साथ जोड़ने के लिए आदिम परतों और सम्मेलनों को परिभाषित करता है, जिससे मॉडल और प्रयोग बनाना आसान हो जाता है।

एक मॉडल एक struct है जो Layer के अनुरूप है, जिसका अर्थ है कि यह एक callAsFunction(_:) विधि को परिभाषित करता है जो Tensor s को आउटपुट करने के लिए इनपुट Tensor s को मैप करता है। callAsFunction(_:) विधि अक्सर सबलेयर्स के माध्यम से इनपुट को अनुक्रमित करती है। आइए एक IrisModel को परिभाषित करें जो इनपुट को तीन 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()

सक्रियण फ़ंक्शन परत में प्रत्येक नोड के आउटपुट आकार को निर्धारित करता है। ये गैर-रैखिकता महत्वपूर्ण हैं- इनके बिना मॉडल एक परत के बराबर होगा। कई उपलब्ध सक्रियण हैं, लेकिन छिपी हुई परतों के लिए ReLU सामान्य है।

छिपी हुई परतों और न्यूरॉन्स की आदर्श संख्या समस्या और डेटासेट पर निर्भर करती है। मशीन लर्निंग के कई पहलुओं की तरह, तंत्रिका नेटवर्क का सबसे अच्छा आकार चुनने के लिए ज्ञान और प्रयोग के मिश्रण की आवश्यकता होती है। एक नियम के रूप में, छिपी हुई परतों और न्यूरॉन्स की संख्या में वृद्धि आम तौर पर एक अधिक शक्तिशाली मॉडल बनाती है, जिसे प्रभावी ढंग से प्रशिक्षित करने के लिए अधिक डेटा की आवश्यकता होती है।

मॉडल का उपयोग करना

आइए एक नज़र डालते हैं कि यह मॉडल सुविधाओं के एक बैच के साथ क्या करता है:

// 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]]

यहां, प्रत्येक उदाहरण प्रत्येक वर्ग के लिए एक लॉगिट देता है।

इन लॉग को प्रत्येक वर्ग के लिए प्रायिकता में बदलने के लिए, सॉफ्टमैक्स फ़ंक्शन का उपयोग करें:

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]]

सभी वर्गों में argmax लेने से हमें अनुमानित वर्ग सूचकांक मिलता है। लेकिन, मॉडल को अभी तक प्रशिक्षित नहीं किया गया है, इसलिए ये अच्छी भविष्यवाणियां नहीं हैं।

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]

मॉडल को प्रशिक्षित करें

प्रशिक्षण मशीन सीखने का चरण है जब मॉडल को धीरे-धीरे अनुकूलित किया जाता है, या मॉडल डेटासेट सीखता है। लक्ष्य अनदेखी डेटा के बारे में भविष्यवाणियां करने के लिए प्रशिक्षण डेटासेट की संरचना के बारे में पर्याप्त सीखना है। यदि आप प्रशिक्षण डेटासेट के बारे में बहुत अधिक सीखते हैं, तो भविष्यवाणियां केवल उस डेटा के लिए काम करती हैं जिसे उसने देखा है और सामान्यीकरण योग्य नहीं होगा। इस समस्या को ओवरफिटिंग कहा जाता है - यह किसी समस्या को हल करने के तरीके को समझने के बजाय उत्तरों को याद रखने जैसा है।

परितारिका वर्गीकरण समस्या पर्यवेक्षित मशीन सीखने का एक उदाहरण है: मॉडल को उन उदाहरणों से प्रशिक्षित किया जाता है जिनमें लेबल होते हैं। अनुपयोगी मशीन लर्निंग में, उदाहरणों में लेबल नहीं होते हैं। इसके बजाय, मॉडल आमतौर पर सुविधाओं के बीच पैटर्न ढूंढता है।

हानि फ़ंक्शन चुनें

प्रशिक्षण और मूल्यांकन दोनों चरणों को मॉडल के नुकसान की गणना करने की आवश्यकता है। यह मापता है कि मॉडल की भविष्यवाणियां वांछित लेबल से कितनी दूर हैं, दूसरे शब्दों में, मॉडल कितना खराब प्रदर्शन कर रहा है। हम इस मान को कम करना या अनुकूलित करना चाहते हैं।

हमारा मॉडल softmaxCrossEntropy(logits:labels:) फ़ंक्शन का उपयोग करके इसके नुकसान की गणना करेगा जो मॉडल की वर्ग संभाव्यता पूर्वानुमान और वांछित लेबल लेता है, और उदाहरणों में औसत नुकसान देता है।

आइए वर्तमान अप्रशिक्षित मॉडल के नुकसान की गणना करें:

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

एक अनुकूलक बनाएं

एक अनुकूलक loss फ़ंक्शन को कम करने के लिए मॉडल के चरों पर गणना किए गए ग्रेडिएंट लागू करता है। आप हानि फलन को एक घुमावदार सतह के रूप में सोच सकते हैं (चित्र 3 देखें) और हम चारों ओर घूमकर इसका निम्नतम बिंदु खोजना चाहते हैं। ढाल सबसे तेज चढ़ाई की दिशा में इंगित करते हैं—इसलिए हम विपरीत दिशा में यात्रा करेंगे और पहाड़ी से नीचे जाएंगे। प्रत्येक बैच के नुकसान और ढाल की गणना करके, हम प्रशिक्षण के दौरान मॉडल को समायोजित करेंगे। धीरे-धीरे, मॉडल को नुकसान को कम करने के लिए वज़न और पूर्वाग्रह का सबसे अच्छा संयोजन मिलेगा। और नुकसान जितना कम होगा, मॉडल की भविष्यवाणी उतनी ही बेहतर होगी।

3डी स्पेस में समय के साथ ऑप्टिमाइज़ेशन एल्गोरिदम की कल्पना की गई।
चित्रा 3. 3 डी अंतरिक्ष में समय के साथ देखे गए अनुकूलन एल्गोरिदम।
(स्रोत: स्टैनफोर्ड क्लास CS231n , MIT लाइसेंस, इमेज क्रेडिट: एलेक रैडफोर्ड )

TensorFlow के लिए स्विफ्ट में प्रशिक्षण के लिए कई अनुकूलन एल्गोरिदम उपलब्ध हैं। यह मॉडल SGD ऑप्टिमाइज़र का उपयोग करता है जो स्टोकेस्टिक ग्रेडिएंट डिसेंट (SGD) एल्गोरिथम को लागू करता है। learningRate की दर पहाड़ी के नीचे प्रत्येक पुनरावृत्ति के लिए कदम का आकार निर्धारित करती है। यह एक हाइपरपैरामीटर है जिसे आप आमतौर पर बेहतर परिणाम प्राप्त करने के लिए समायोजित करेंगे।

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

आइए एक सिंगल ग्रेडिएंट डिसेंट स्टेप लेने के लिए optimizer का उपयोग करें। सबसे पहले, हम मॉडल के संबंध में नुकसान की ढाल की गणना करते हैं:

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

इसके बाद, हम उस ग्रेडिएंट को पास करते हैं जिसे हमने अभी-अभी ऑप्टिमाइज़र के लिए परिकलित किया है, जो उसके अनुसार मॉडल के अलग-अलग वैरिएबल को अपडेट करता है:

optimizer.update(&model, along: grads)

यदि हम फिर से नुकसान की गणना करते हैं, तो यह छोटा होना चाहिए, क्योंकि ग्रेडिएंट डिसेंट स्टेप्स (आमतौर पर) नुकसान को कम करते हैं:

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

प्लेसहोल्डर33

प्रशिक्षण पाश

सभी टुकड़ों के साथ, मॉडल प्रशिक्षण के लिए तैयार है! एक प्रशिक्षण लूप बेहतर भविष्यवाणियां करने में मदद करने के लिए डेटासेट उदाहरणों को मॉडल में फीड करता है। निम्नलिखित कोड ब्लॉक इन प्रशिक्षण चरणों को सेट करता है:

  1. प्रत्येक युग पर पुनरावृति। एक युग डेटासेट के माध्यम से एक पास है।
  2. एक युग के भीतर, प्रशिक्षण युग में प्रत्येक बैच पर पुनरावृति करें
  3. बैच को मिलाएं और इसकी विशेषताओं ( x ) और लेबल ( y ) को पकड़ें।
  4. कोलेटेड बैच की विशेषताओं का उपयोग करते हुए, एक भविष्यवाणी करें और इसकी तुलना लेबल से करें। भविष्यवाणी की अशुद्धि को मापें और इसका उपयोग मॉडल के नुकसान और ग्रेडिएंट की गणना करने के लिए करें।
  5. मॉडल के वेरिएबल्स को अपडेट करने के लिए ग्रेडिएंट डिसेंट का उपयोग करें।
  6. विज़ुअलाइज़ेशन के लिए कुछ आँकड़ों पर नज़र रखें।
  7. प्रत्येक युग के लिए दोहराएं।

epochCount वैरिएबल डेटासेट संग्रह पर लूप करने की संख्या है। प्रति-सहज रूप से, एक मॉडल को लंबे समय तक प्रशिक्षण देना बेहतर मॉडल की गारंटी नहीं देता है। epochCount एक हाइपरपैरामीटर है जिसे आप ट्यून कर सकते हैं। सही संख्या चुनने के लिए आमतौर पर अनुभव और प्रयोग दोनों की आवश्यकता होती है।

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

समय के साथ हानि फ़ंक्शन की कल्पना करें

हालांकि यह मॉडल की प्रशिक्षण प्रगति को प्रिंट करने में मददगार है, लेकिन इस प्रगति को देखना अक्सर अधिक सहायक होता है। हम पायथन के matplotlib मॉड्यूल का उपयोग करके बुनियादी चार्ट बना सकते हैं।

इन चार्टों की व्याख्या करने में कुछ अनुभव होता है, लेकिन आप वास्तव में नुकसान को कम होते देखना चाहते हैं और सटीकता में वृद्धि करना चाहते हैं।

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

पीएनजी

Use `print()` to show values.

ध्यान दें कि ग्राफ के y-अक्ष शून्य-आधारित नहीं हैं।

मॉडल की प्रभावशीलता का मूल्यांकन करें

अब जब मॉडल प्रशिक्षित हो गया है, तो हम इसके प्रदर्शन के कुछ आंकड़े प्राप्त कर सकते हैं।

मूल्यांकन का अर्थ यह निर्धारित करना है कि मॉडल कितनी प्रभावी ढंग से भविष्यवाणियां करता है। आईरिस वर्गीकरण में मॉडल की प्रभावशीलता को निर्धारित करने के लिए, मॉडल को कुछ सीपल और पंखुड़ी माप पास करें और मॉडल से यह अनुमान लगाने के लिए कहें कि वे किस आईरिस प्रजाति का प्रतिनिधित्व करते हैं। फिर वास्तविक लेबल के विरुद्ध मॉडल की भविष्यवाणी की तुलना करें। उदाहरण के लिए, एक मॉडल जिसने आधे इनपुट उदाहरणों पर सही प्रजाति चुनी है, उसकी सटीकता 0.5 है। चित्र 4 थोड़ा अधिक प्रभावी मॉडल दिखाता है, जिसमें 5 में से 4 भविष्यवाणियां 80% सटीकता पर सही होती हैं:

उदाहरण विशेषताएं लेबल मॉडल भविष्यवाणी
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
चित्रा 4. एक आईरिस क्लासिफायरियर जो 80% सटीक है।

परीक्षण डेटासेट सेट करें

मॉडल का मूल्यांकन मॉडल के प्रशिक्षण के समान है। सबसे बड़ा अंतर यह है कि उदाहरण प्रशिक्षण सेट के बजाय एक अलग परीक्षण सेट से आते हैं। किसी मॉडल की प्रभावशीलता का निष्पक्ष मूल्यांकन करने के लिए, किसी मॉडल का मूल्यांकन करने के लिए उपयोग किए जाने वाले उदाहरण मॉडल को प्रशिक्षित करने के लिए उपयोग किए जाने वाले उदाहरणों से भिन्न होने चाहिए।

परीक्षण डेटासेट के लिए सेटअप प्रशिक्षण डेटासेट के सेटअप के समान है। 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)

अब इसे IrisBatch तों की एक सरणी में लोड करें:

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

परीक्षण डेटासेट पर मॉडल का मूल्यांकन करें

प्रशिक्षण चरण के विपरीत, मॉडल केवल परीक्षण डेटा के एकल युग का मूल्यांकन करता है। निम्नलिखित कोड सेल में, हम परीक्षण सेट में प्रत्येक उदाहरण पर पुनरावृति करते हैं और वास्तविक लेबल के विरुद्ध मॉडल की भविष्यवाणी की तुलना करते हैं। इसका उपयोग पूरे परीक्षण सेट में मॉडल की सटीकता को मापने के लिए किया जाता है।

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

हम पहले बैच पर देख सकते हैं, उदाहरण के लिए, मॉडल आमतौर पर सही होता है:

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]

भविष्यवाणी करने के लिए प्रशिक्षित मॉडल का उपयोग करें

हमने एक मॉडल को प्रशिक्षित किया है और दिखाया है कि यह आईरिस प्रजातियों को वर्गीकृत करने में अच्छा है - लेकिन सही नहीं है। अब बिना लेबल वाले उदाहरणों पर कुछ भविष्यवाणियां करने के लिए प्रशिक्षित मॉडल का उपयोग करते हैं; यानी ऐसे उदाहरणों पर जिनमें विशेषताएं तो हैं लेकिन लेबल नहीं हैं।

वास्तविक जीवन में, लेबल न किए गए उदाहरण कई अलग-अलग स्रोतों से आ सकते हैं जिनमें ऐप्स, CSV फ़ाइलें और डेटा फ़ीड शामिल हैं। अभी के लिए, हम उनके लेबल की भविष्यवाणी करने के लिए तीन गैर-लेबल वाले उदाहरण मैन्युअल रूप से प्रदान करने जा रहे हैं। याद रखें, लेबल नंबरों को नामित प्रतिनिधित्व के लिए मैप किया जाता है:

  • 0 : आइरिस सेटोसा
  • 1 : आईरिस वर्सिकलर
  • 2 : आईरिस वर्जिनिका
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])