-
Notifications
You must be signed in to change notification settings - Fork 149
/
Copy pathImagewoof.swift
122 lines (111 loc) · 5.33 KB
/
Imagewoof.swift
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
// Copyright 2020 The TensorFlow Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// Original source:
// "Imagenette"
// Jeremy Howard
// https://github.com/fastai/Imagenette
import Foundation
import ModelSupport
import TensorFlow
public struct Imagewoof<Entropy: RandomNumberGenerator> {
/// Type of the collection of non-collated batches.
public typealias Batches = Slices<Sampling<[(file: URL, label: Int32)], ArraySlice<Int>>>
/// The type of the training data, represented as a sequence of epochs, which
/// are collection of batches.
public typealias Training = LazyMapSequence<
TrainingEpochs<[(file: URL, label: Int32)], Entropy>,
LazyMapSequence<Batches, LabeledImage>
>
/// The type of the validation data, represented as a collection of batches.
public typealias Validation = LazyMapSequence<Slices<[(file: URL, label: Int32)]>, LabeledImage>
/// The training epochs.
public let training: Training
/// The validation batches.
public let validation: Validation
/// Creates an instance with `batchSize`.
///
/// - Parameters:
/// - batchSize: Number of images provided per batch.
/// - entropy: A source of randomness used to shuffle sample
/// ordering. It will be stored in `self`, so if it is only pseudorandom
/// and has value semantics, the sequence of epochs is deterministic and not
/// dependent on other operations.
/// - device: The Device on which resulting Tensors from this dataset will be placed, as well
/// as where the latter stages of any conversion calculations will be performed.
public init(batchSize: Int, entropy: Entropy, device: Device) {
self.init(
batchSize: batchSize, entropy: entropy, device: device, inputSize: ImagenetteSize.resized320,
outputSize: 224)
}
/// Creates an instance with `batchSize` on `device` using `remoteBinaryArchiveLocation`.
///
/// - Parameters:
/// - batchSize: Number of images provided per batch.
/// - entropy: A source of randomness used to shuffle sample ordering. It
/// will be stored in `self`, so if it is only pseudorandom and has value
/// semantics, the sequence of epochs is deterministic and not dependent
/// on other operations.
/// - device: The Device on which resulting Tensors from this dataset will be placed, as well
/// as where the latter stages of any conversion calculations will be performed.
/// - inputSize: Which Imagenette image size variant to use.
/// - outputSize: The square width and height of the images returned from this dataset.
/// - localStorageDirectory: Where to place the downloaded and unarchived dataset.
public init(
batchSize: Int, entropy: Entropy, device: Device, inputSize: ImagenetteSize,
outputSize: Int,
localStorageDirectory: URL = DatasetUtilities.defaultDirectory
.appendingPathComponent("Imagewoof", isDirectory: true)
) {
do {
// Training data
let trainingSamples = try loadImagenetteTrainingDirectory(
inputSize: inputSize, localStorageDirectory: localStorageDirectory, base: "imagewoof")
let mean = Tensor<Float>([0.485, 0.456, 0.406], on: device)
let standardDeviation = Tensor<Float>([0.229, 0.224, 0.225], on: device)
training = TrainingEpochs(samples: trainingSamples, batchSize: batchSize, entropy: entropy)
.lazy.map { (batches: Batches) -> LazyMapSequence<Batches, LabeledImage> in
return batches.lazy.map {
makeImagenetteBatch(
samples: $0, outputSize: outputSize, mean: mean, standardDeviation: standardDeviation,
device: device)
}
}
// Validation data
let validationSamples = try loadImagenetteValidationDirectory(
inputSize: inputSize, localStorageDirectory: localStorageDirectory, base: "imagewoof")
validation = validationSamples.inBatches(of: batchSize).lazy.map {
makeImagenetteBatch(
samples: $0, outputSize: outputSize, mean: mean, standardDeviation: standardDeviation,
device: device)
}
} catch {
fatalError("Could not load Imagewoof dataset: \(error)")
}
}
}
extension Imagewoof: ImageClassificationData where Entropy == SystemRandomNumberGenerator {
/// Creates an instance with `batchSize`, using the SystemRandomNumberGenerator.
public init(batchSize: Int, on device: Device = Device.default) {
self.init(batchSize: batchSize, entropy: SystemRandomNumberGenerator(), device: device)
}
/// Creates an instance with `batchSize`, `inputSize`, and `outputSize`, using the
/// SystemRandomNumberGenerator.
public init(
batchSize: Int, inputSize: ImagenetteSize, outputSize: Int, on device: Device = Device.default
) {
self.init(
batchSize: batchSize, entropy: SystemRandomNumberGenerator(), device: device,
inputSize: inputSize, outputSize: outputSize)
}
}