ชุดข้อมูล

ในโมเดลการเรียนรู้ของเครื่องหลายๆ โมเดล โดยเฉพาะอย่างยิ่งสำหรับการเรียนรู้ภายใต้การดูแล ชุดข้อมูลเป็นส่วนสำคัญของกระบวนการฝึกอบรม Swift สำหรับ TensorFlow ให้ wrappers สำหรับชุดข้อมูลทั่วไปหลายชุดภายในโมดูลชุดข้อมูลใน ที่เก็บแบบจำลอง Wrapper เหล่านี้ทำให้การใช้ชุดข้อมูลทั่วไปกับโมเดลที่ใช้ Swift ง่ายขึ้น และผสานรวมเข้ากับลูปการฝึกทั่วไปของ Swift สำหรับ TensorFlow ได้เป็นอย่างดี

Wrapper ชุดข้อมูลที่ให้มา

เหล่านี้คือ Wrapper ชุดข้อมูลที่มีให้ในปัจจุบันภายในที่เก็บโมเดล:

หากต้องการใช้ชุดข้อมูลชุดใดชุดหนึ่งภายในโครงการ Swift ให้เพิ่ม Datasets เป็นการพึ่งพาเป้าหมาย Swift ของคุณแล้วนำเข้าโมดูล:

import Datasets

Wrapper ชุดข้อมูลส่วนใหญ่ได้รับการออกแบบมาเพื่อสร้างชุดข้อมูลที่ติดป้ายกำกับแบบสุ่ม ตัวอย่างเช่น หากต้องการใช้ชุดข้อมูล CIFAR-10 คุณต้องเริ่มต้นชุดข้อมูลด้วยขนาดแบตช์ที่ต้องการก่อน:

let dataset = CIFAR10(batchSize: 100)

ในการใช้งานครั้งแรก Wrapper ชุดข้อมูล Swift สำหรับ 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) ) และส่งคืนดัชนีตัวเลขของยุคปัจจุบันและลำดับที่แมปอย่างเกียจคร้านเหนือแบทช์ที่สับซึ่งประกอบกันเป็นยุคนั้น ภายในแต่ละยุคการฝึกอบรม ชุดงานจะถูกทำซ้ำและแยกออกมาเพื่อการประมวลผล ในกรณีของ wrapper ชุดข้อมูล CIFAR10 แต่ละชุดจะเป็น LabeledImage ซึ่งจัดเตรียม Tensor<Float> ที่มีรูปภาพทั้งหมดจากชุดนั้นและ Tensor<Int32> พร้อมป้ายกำกับที่ตรงกัน

ในกรณีของ CIFAR-10 ชุดข้อมูลทั้งหมดมีขนาดเล็กและสามารถโหลดลงในหน่วยความจำได้ในคราวเดียว แต่สำหรับชุดข้อมูลขนาดใหญ่อื่นๆ ชุดข้อมูลจะถูกโหลดอย่างเกียจคร้านจากดิสก์และประมวลผล ณ จุดที่ได้รับแต่ละชุด วิธีนี้จะช่วยป้องกันหน่วยความจำหมดด้วยชุดข้อมูลขนาดใหญ่เหล่านั้น

API ยุค

Wrapper ชุดข้อมูลเหล่านี้ส่วนใหญ่สร้างขึ้นบนโครงสร้างพื้นฐานที่ใช้ร่วมกันซึ่งเราเรียกว่า Epochs API Epochs มีส่วนประกอบที่ยืดหยุ่นซึ่งออกแบบมาเพื่อรองรับชุดข้อมูลประเภทต่างๆ ตั้งแต่ข้อความไปจนถึงรูปภาพ และอื่นๆ

หากคุณต้องการสร้าง Wrapper ชุดข้อมูล Swift ของคุณเอง คุณอาจต้องการใช้ Epochs API เพื่อดำเนินการดังกล่าว อย่างไรก็ตาม สำหรับกรณีทั่วไป เช่น ชุดข้อมูลการจัดหมวดหมู่รูปภาพ เราขอแนะนำเป็นอย่างยิ่งให้เริ่มจากเทมเพลตโดยอิงจาก Wrapper ชุดข้อมูลที่มีอยู่แล้วแก้ไขให้ตรงตามความต้องการเฉพาะของคุณ

ตามตัวอย่าง เรามาตรวจสอบ wrapper ชุดข้อมูล 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) สำหรับแต่ละภาพในชุดข้อมูลการฝึกอบรม จากนั้นสิ่งนี้จะมอบให้กับ TrainingEpochs(samples:batchSize:entropy:) เพื่อสร้างลำดับยุคที่ไม่มีที่สิ้นสุดด้วยแบตช์ของ batchSize คุณสามารถจัดเตรียมตัวสร้างตัวเลขสุ่มของคุณเองได้ในกรณีที่คุณอาจต้องการลักษณะการทำงานเป็นชุดที่กำหนดได้ แต่ตามค่าเริ่มต้น SystemRandomNumberGenerator จะถูกใช้

จากนั้น แผนที่แบบ Lazy Map ทั่วทั้งแบตช์จะสิ้นสุดลงในฟังก์ชัน 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)
}

บรรทัดสองบรรทัดของฟังก์ชันนี้จะเชื่อมไบต์ data ทั้งหมดจาก BatchSamples ขาเข้าเข้ากับ Tensor<UInt8> ที่ตรงกับเค้าโครงไบต์ของรูปภาพภายในชุดข้อมูลดิบ CIFAR-10 ถัดไป ช่องรูปภาพจะถูกจัดเรียงใหม่เพื่อให้ตรงกับที่คาดหวังในโมเดลการจัดหมวดหมู่รูปภาพมาตรฐานของเรา และข้อมูลรูปภาพจะถูกแปลงใหม่ใน Tensor<Float> เพื่อการใช้โมเดล

สามารถระบุพารามิเตอร์การทำให้เป็นมาตรฐานที่เป็นตัวเลือกเพื่อปรับค่าช่องสัญญาณภาพเพิ่มเติม ซึ่งเป็นกระบวนการที่พบบ่อยเมื่อฝึกโมเดลการจำแนกประเภทรูปภาพจำนวนมาก พารามิเตอร์การทำให้เป็นมาตรฐาน Tensor s ถูกสร้างขึ้นหนึ่งครั้งในการเริ่มต้นชุดข้อมูล จากนั้นส่งผ่านไปยัง makeBatch() เพื่อเป็นการปรับให้เหมาะสมที่สุดเพื่อป้องกันการสร้างเทนเซอร์ชั่วคราวขนาดเล็กซ้ำ ๆ ที่มีค่าเดียวกัน

สุดท้าย ป้ายกำกับจำนวนเต็มจะถูกวางไว้ใน Tensor<Int32> และคู่เมตริกซ์รูปภาพ / ป้ายกำกับที่ส่งคืนใน LabeledImage LabeledImage เป็นกรณีเฉพาะของ LabeledData ซึ่งเป็นโครงสร้างที่มีข้อมูลและป้ายกำกับที่สอดคล้องกับโปรโตคอล Collatable ของ Eppch API

หากต้องการตัวอย่างเพิ่มเติมของ Epochs API ในชุดข้อมูลประเภทต่างๆ คุณสามารถตรวจสอบ Wrapper ชุดข้อมูลอื่นๆ ภายในที่เก็บโมเดลได้