此页面由 Cloud Translation API 翻译。
Switch to English

模型训练演练

在TensorFlow.org上查看 在GitHub上查看源代码

本指南通过构建按物种对鸢尾花进行分类的机器学习模型,为TensorFlow引入了Swift。它使用Swift将TensorFlow用于:

  1. 建立模型
  2. 在示例数据上训练该模型,并
  3. 使用模型对未知数据进行预测。

TensorFlow编程

本指南将这些高级Swift用于TensorFlow概念:

  • 使用Epochs API导入数据。
  • 使用Swift抽象构建模型。
  • 当纯Swift库不可用时,请使用通过Swift的Python互操作性使用Python库。

本教程的结构类似于许多TensorFlow程序:

  1. 导入并解析数据集。
  2. 选择模型的类型。
  3. 训练模型。
  4. 评估模型的有效性。
  5. 使用训练有素的模型进行预测。

安装程序

配置导入

导入TensorFlow和一些有用的Python模块。

 import TensorFlow
#if canImport(PythonKit)
    import PythonKit
#else
    import Python
#endif
 
 // This cell is here to display the plots in a Jupyter Notebook.
// Do not copy it into another environment.
%include "EnableIPythonDisplay.swift"
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. 鸢尾花 (由Radomil撰写 ,CC BY-SA 3.0), 鸢尾花 (由Dlanglois撰写 ,CC BY-SA 3.0)和弗吉尼亚 鸢尾花 (由Frank Mayfield 撰写 ,CC BY-SA 2.0)。

幸运的是,已经有人用萼片和花瓣测量数据创建了120个鸢尾花数据集 。这是经典数据集,在初学者机器学习分类问题中很流行。

导入并解析训练数据集

下载数据集文件并将其转换为可由该Swift程序使用的结构。

下载数据集

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

每个标签都与字符串名称(例如“ setosa”)相关联,但是机器学习通常依赖于数值。标签编号映射到命名表示形式,例如:

  • 0 :鸢尾
  • 1 :杂色鸢尾
  • 2 :鸢尾

有关功能和标签的更多信息,请参阅机器学习速成课程ML术语部分

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

使用Epochs API创建数据集

TensorFlow的Epochs API的Swift是一个高级API,用于读取数据并将其转换为用于培训的形式。

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

由于我们下载的数据集为CSV格式,因此让我们编写一个函数以IrisBatch对象列表的形式加载数据

 /// Initialize an `IrisBatch` dataset from a CSV file.
func loadIrisDatasetFromCSV(
        contentsOfCSVFile: String, hasHeader: Bool, featureColumns: [Int], labelColumns: [Int]) -> [IrisBatch] {
        let np = Python.import("numpy")

        let featuresNp = np.loadtxt(
            contentsOfCSVFile,
            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 numpy 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(
            contentsOfCSVFile,
            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 numpy 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)}

    }
 

现在,我们可以使用CSV加载功能加载训练数据集并创建一个TrainingEpochs对象

 let trainingDataset: [IrisBatch] = loadIrisDatasetFromCSV(contentsOfCSVFile: 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("First batch of labels: \(firstTrainLabels)")
 
First batch of features: [[6.0, 3.0, 4.8, 1.8],
 [6.3, 2.5, 5.0, 1.9],
 [5.7, 2.8, 4.5, 1.3],
 [5.6, 2.9, 3.6, 1.3],
 [6.1, 3.0, 4.9, 1.8],
 [5.5, 3.5, 1.3, 0.2],
 [7.9, 3.8, 6.4, 2.0],
 [5.1, 3.5, 1.4, 0.3],
 [6.7, 3.3, 5.7, 2.1],
 [5.1, 3.8, 1.9, 0.4],
 [5.0, 2.3, 3.3, 1.0],
 [7.0, 3.2, 4.7, 1.4],
 [6.8, 3.2, 5.9, 2.3],
 [4.6, 3.6, 1.0, 0.2],
 [6.7, 3.1, 4.4, 1.4],
 [4.9, 3.1, 1.5, 0.1],
 [5.6, 2.7, 4.2, 1.3],
 [5.8, 2.8, 5.1, 2.4],
 [4.8, 3.0, 1.4, 0.1],
 [6.1, 2.8, 4.0, 1.3],
 [6.3, 2.3, 4.4, 1.3],
 [6.3, 3.4, 5.6, 2.4],
 [4.6, 3.4, 1.4, 0.3],
 [6.6, 3.0, 4.4, 1.4],
 [6.4, 2.8, 5.6, 2.2],
 [6.4, 3.1, 5.5, 1.8],
 [4.7, 3.2, 1.3, 0.2],
 [6.1, 2.9, 4.7, 1.4],
 [5.0, 3.2, 1.2, 0.2],
 [6.3, 2.7, 4.9, 1.8],
 [5.2, 3.5, 1.5, 0.2],
 [6.4, 3.2, 4.5, 1.5]]
First batch of labels: [2, 2, 1, 1, 2, 0, 2, 0, 2, 0, 1, 1, 2, 0, 1, 0, 1, 2, 0, 1, 1, 2, 0, 1, 2, 2, 0, 1, 0, 2, 0, 1]

请注意,第一个batchSize示例的功能被组合在一起(或成批组合 )为firstTrainFeatures ,并且第一个batchSize示例的标签被分组为firstTrainLabels

您可以使用Python的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()
 

png

None

选择型号类型

为什么要模型?

模型是要素与标签之间的关系。对于虹膜分类问题,模型定义了萼片和花瓣的测量值与预测的虹膜种类之间的关系。一些简单的模型可以用几行代数来描述,但是复杂的机器学习模型具有大量难以概括的参数。

您可以在使用机器学习的情况下确定这四个特征与虹膜种类之间的关系吗?也就是说,您可以使用传统的编程技术(例如,许多条件语句)来创建模型吗?也许-如果您对数据集进行足够长的分析,以确定特定物种的花瓣和萼片测量值之间的关系。在更复杂的数据集上,这变得很困难,甚至不可能实现。好的机器学习方法可以为您确定模型 。如果您将足够的代表性示例输入正确的机器学习模型类型,该程序将为您找出关系。

选择型号

我们需要选择要训练的模型。有很多类型的模型,挑选一个好的模型需要经验。本教程使用神经网络解决虹膜分类问题。 神经网络可以找到特征和标签之间的复杂关系。它是一种高度结构化的图,分为一个或多个隐藏层 。每个隐藏层由一个或多个神经元组成 。神经网络有几种类别,该程序使用密集的或完全连接的神经网络 :一层中的神经元从上一层中的每个神经元接收输入连接。例如,图2说明了一个密集的神经网络,它由一个输入层,两个隐藏层和一个输出层组成:

网络体系结构图:输入,2个隐藏层和输出
图2.具有特征,隐藏层和预测的神经网络。

当训练来自图2的模型并提供一个未标记的示例时,它会产生三个预测:该花是给定虹膜种类的可能性。这种预测称为推断 。对于此示例,输出预测的总和为1.0。在图2中,此预测分解为: 0.02 鸢尾花0.02杂色鸢尾花0.95virginica鸢尾花0.03 。这意味着该模型以95%的概率预测未标记的示例花是鸢尾花

使用Swift for TensorFlow深度学习库创建模型

Swift for TensorFlow深度学习库定义了将它们连接在一起的原始层和约定,这使得构建模型和实验变得容易。

模型是符合Layerstruct ,这意味着它定义了一个callAsFunction(_:)方法,该方法将输入Tensor映射到输出TensorcallAsFunction(_:)方法通常简单地通过子层对输入进行排序。让我们定义一个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)
firstTrainPredictions[0..<5]
 
[[   1.454208,  0.24379121,  -0.9649837],
 [  1.4504895,  0.31482732, -0.88196427],
 [  1.4068713,  0.26030555,  -0.8821216],
 [    1.48215,   0.2896214,  -0.8973131],
 [  1.4721411,  0.25258976,  -0.9691639]]

在这里,每个示例都会为每个类返回一个logit

要将这些对数转换为每个类的概率,请使用softmax函数:

 softmax(firstTrainPredictions[0..<5])
 
[[  0.7209459,  0.21489452, 0.064159505],
 [ 0.70508605,  0.22648023, 0.068433754],
 [ 0.70467466,   0.2238935, 0.071431816],
 [  0.7163051,  0.21736495, 0.066330045],
 [  0.7233744,  0.21365778, 0.062967695]]

跨类采用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: [2, 2, 1, 1, 2, 0, 2, 0, 2, 0, 1, 1, 2, 0, 1, 0, 1, 2, 0, 1, 1, 2, 0, 1, 2, 2, 0, 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.6138709

 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.6138709

接下来,我们将刚刚计算出的梯度传递给优化器,优化器将相应地更新模型的可微变量:

 optimizer.update(&model, along: grads)
 

如果我们再次计算损耗,则它应该较小,因为梯度下降步骤(通常)会减少损耗:

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

训练循环

所有零件都准备就绪,模型就可以训练了!训练循环将数据集示例输入模型,以帮助其做出更好的预测。以下代码块设置了这些训练步骤:

  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.316198, Accuracy: 0.36458334
Epoch 50: Loss: 0.5683666, Accuracy: 0.6875
Epoch 100: Loss: 0.42986333, Accuracy: 0.8541667
Epoch 150: Loss: 0.3263924, Accuracy: 0.9583333
Epoch 200: Loss: 0.24369155, Accuracy: 0.9791667
Epoch 250: Loss: 0.17126365, Accuracy: 0.9791667
Epoch 300: Loss: 0.1455363, Accuracy: 0.96875
Epoch 350: Loss: 0.121186025, Accuracy: 0.9895833
Epoch 400: Loss: 0.11745409, Accuracy: 0.9791667
Epoch 450: Loss: 0.08234135, Accuracy: 0.9895833

随时间可视化损失函数

虽然打印出模型的训练进度会有所帮助,但查看此进度通常会更有帮助。我们可以使用Python的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()
 

png

None

请注意,图的y轴不是从零开始的。

评估模型的有效性

现在已经对模型进行了训练,我们可以获得有关其性能的一些统计信息。

评估意味着确定模型进行预测的效率。要确定模型在虹膜分类中的有效性,请将一些萼片和花瓣的测量值传递给模型,并要求模型预测它们代表的虹膜种类。然后将模型的预测与实际标签进行比较。例如,在一半输入示例中选择正确物种的模型的精度0.5 。图4显示了一个稍微有效的模型,在80%的准确度下,正确的5个预测中有4个得到正确的:

示例功能标签模型预测
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(
    contentsOfCSVFile: 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.9853947,  0.014605234, 1.049226e-10])
Example 1 prediction: Iris versicolor ([0.0022595704,    0.9383183,  0.059422087])
Example 2 prediction: Iris virginica ([2.2416664e-06,    0.06604068,    0.93395704])

创建一个优化器

优化器将计算出的梯度应用于模型变量,以最小化loss函数。您可以将损失函数视为曲面(请参见图3),我们希望通过走动来找到其最低点。梯度指向最陡峭的上升方向-因此我们将以相反的方式行进并下山。通过迭代计算每批的损耗和梯度,我们将在训练期间调整模型。该模型将逐渐找到权重和偏差的最佳组合,以最大程度地减少损失。损失越小,模型的预测越好。

优化算法在3D空间中随时间可视化。
图3.在3D空间中随时间可视化的优化算法。
(来源: 斯坦福大学CS231n级 ,麻省理工学院许可,图片来源: Alec Radford

Swift for TensorFlow具有许多可用于训练的优化算法 。该模型使用SGD优化器来实现随机梯度下降 (SGD)算法。 learningRate设置步长大小,用于每次下坡迭代。这是一个超参数 ,您通常会对其进行调整以获得更好的结果。