डेटासेट

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

डेटासेट रैपर प्रदान किए गए

ये मॉडल रिपॉजिटरी के भीतर वर्तमान में उपलब्ध कराए गए डेटासेट रैपर हैं:

स्विफ्ट प्रोजेक्ट के भीतर इन डेटासेट रैपर्स में से एक का उपयोग करने के लिए, Datasets अपने स्विफ्ट लक्ष्य पर निर्भरता के रूप में जोड़ें और मॉड्यूल आयात करें:

import Datasets

अधिकांश डेटासेट रैपर लेबल किए गए डेटा के बेतरतीब ढंग से फेरबदल किए गए बैचों का उत्पादन करने के लिए डिज़ाइन किए गए हैं। उदाहरण के लिए, CIFAR-10 डेटासेट का उपयोग करने के लिए, आप पहले इसे वांछित बैच आकार के साथ प्रारंभ करें:

let dataset = CIFAR10(batchSize: 100)

पहले उपयोग पर, TensorFlow डेटासेट रैपर के लिए स्विफ्ट स्वचालित रूप से आपके लिए मूल डेटासेट डाउनलोड करेगा, सभी प्रासंगिक अभिलेखों को निकालेगा और पार्स करेगा, और फिर संसाधित डेटासेट को उपयोगकर्ता-स्थानीय कैश निर्देशिका में संग्रहीत करेगा। उसी डेटासेट के बाद के उपयोग सीधे स्थानीय कैश से लोड होंगे।

इस डेटासेट को शामिल करते हुए एक मैन्युअल प्रशिक्षण लूप स्थापित करने के लिए, आप निम्न जैसा कुछ उपयोग करेंगे:

for (epoch, epochBatches) in dataset.training.prefix(100).enumerated() {
  Context.local.learningPhase = .training
  ...
  for batch in epochBatches {
    let (images, labels) = (batch.data, batch.label)
    ...
  }
}

उपरोक्त 100 युगों ( .prefix(100) ) के माध्यम से एक पुनरावर्तक सेट करता है, और वर्तमान युग का संख्यात्मक सूचकांक और उस युग को बनाने वाले फेरबदल वाले बैचों पर एक आलसी-मैप अनुक्रम लौटाता है। प्रत्येक प्रशिक्षण युग के भीतर, बैचों को पुनरावृत्त किया जाता है और प्रसंस्करण के लिए निकाला जाता है। CIFAR10 डेटासेट रैपर के मामले में, प्रत्येक बैच एक LabeledImage है, जो एक Tensor<Float> प्रदान करता है जिसमें उस बैच की सभी छवियां और एक Tensor<Int32> उनके मिलान लेबल के साथ होता है।

CIFAR-10 के मामले में, संपूर्ण डेटासेट छोटा होता है और इसे एक समय में मेमोरी में लोड किया जा सकता है, लेकिन अन्य बड़े डेटासेट के लिए बैचों को डिस्क से आराम से लोड किया जाता है और उस बिंदु पर संसाधित किया जाता है जहां प्रत्येक बैच प्राप्त होता है। यह उन बड़े डेटासेट के साथ मेमोरी थकावट को रोकता है।

युग एपीआई

इनमें से अधिकांश डेटासेट रैपर एक साझा बुनियादी ढांचे पर बनाए गए हैं जिन्हें हमने एपोच एपीआई कहा है। एपोच्स लचीले घटक प्रदान करता है जिसका उद्देश्य टेक्स्ट से लेकर छवियों और अन्य विभिन्न प्रकार के डेटासेट प्रकारों का समर्थन करना है।

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

उदाहरण के तौर पर, आइए CIFAR-10 डेटासेट रैपर की जांच करें और यह कैसे काम करता है। प्रशिक्षण डेटासेट का मूल यहाँ परिभाषित किया गया है:

let trainingSamples = loadCIFARTrainingFiles(in: localStorageDirectory)
training = TrainingEpochs(samples: trainingSamples, batchSize: batchSize, entropy: entropy)
  .lazy.map { (batches: Batches) -> LazyMapSequence<Batches, LabeledImage> in
    return batches.lazy.map{
      makeBatch(samples: $0, mean: mean, standardDeviation: standardDeviation, device: device)
  }
}

loadCIFARTrainingFiles() फ़ंक्शन का परिणाम प्रशिक्षण डेटासेट में प्रत्येक छवि के लिए (data: [UInt8], label: Int32) टुपल्स की एक सरणी है। फिर इसे batchSize के बैचों के साथ युगों का एक अनंत अनुक्रम बनाने के लिए TrainingEpochs(samples:batchSize:entropy:) को प्रदान किया जाता है। आप उन मामलों में अपना स्वयं का यादृच्छिक संख्या जनरेटर प्रदान कर सकते हैं जहां आप नियतात्मक बैचिंग व्यवहार चाहते हैं, लेकिन डिफ़ॉल्ट रूप से SystemRandomNumberGenerator का उपयोग किया जाता है।

वहां से, बैचों पर आलसी मानचित्र makeBatch(samples:mean:standardDeviation:device:) फ़ंक्शन में समाप्त होते हैं। यह एक कस्टम फ़ंक्शन है जहां CIFAR-10 डेटासेट के लिए वास्तविक छवि प्रसंस्करण पाइपलाइन स्थित है, तो आइए उस पर एक नज़र डालें:

fileprivate func makeBatch<BatchSamples: Collection>(
  samples: BatchSamples, mean: Tensor<Float>?, standardDeviation: Tensor<Float>?, device: Device
) -> LabeledImage where BatchSamples.Element == (data: [UInt8], label: Int32) {
  let bytes = samples.lazy.map(\.data).reduce(into: [], +=)
  let images = Tensor<UInt8>(shape: [samples.count, 3, 32, 32], scalars: bytes, on: device)

  var imageTensor = Tensor<Float>(images.transposed(permutation: [0, 2, 3, 1]))
  imageTensor /= 255.0
  if let mean = mean, let standardDeviation = standardDeviation {
    imageTensor = (imageTensor - mean) / standardDeviation
  }

  let labels = Tensor<Int32>(samples.map(\.label), on: device)
  return LabeledImage(data: imageTensor, label: labels)
}

इस फ़ंक्शन की दो पंक्तियाँ आने वाले BatchSamples से सभी data बाइट्स को एक Tensor<UInt8> में जोड़ती हैं जो कच्चे CIFAR-10 डेटासेट के भीतर छवियों के बाइट लेआउट से मेल खाती है। इसके बाद, छवि चैनलों को हमारे मानक छवि वर्गीकरण मॉडल में अपेक्षित मिलान करने के लिए पुन: व्यवस्थित किया जाता है और मॉडल खपत के लिए छवि डेटा को Tensor<Float> में फिर से डाला जाता है।

छवि चैनल मूल्यों को और अधिक समायोजित करने के लिए वैकल्पिक सामान्यीकरण पैरामीटर प्रदान किए जा सकते हैं, एक प्रक्रिया जो कई छवि वर्गीकरण मॉडल को प्रशिक्षित करते समय आम है। सामान्यीकरण पैरामीटर Tensor s को डेटासेट आरंभीकरण के समय एक बार बनाया जाता है और फिर समान मानों के साथ छोटे अस्थायी टेंसरों के बार-बार निर्माण को रोकने के लिए अनुकूलन के रूप में makeBatch() में पारित किया जाता है।

अंत में, पूर्णांक लेबल को Tensor<Int32> में रखा जाता है और छवि/लेबल टेंसर जोड़ी को LabeledImage में वापस कर दिया जाता है। LabeledImage LabeledData का एक विशिष्ट मामला है, डेटा और लेबल वाली एक संरचना जो Eppch API के Collatable प्रोटोकॉल के अनुरूप है।

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