C# 中的深度学习:Keras.NET 中的硬币识别,第二部分





5.00/5 (3投票s)
在本文中,我们将研究使用 Keras.NET 实现的用于硬币识别的 CNN。
首先,让我们从 Nuget 包管理器下载 Keras.NET 包。 我们可以在工具 > Nuget 包管理器中找到 Nuget 包管理器。 Keras.NET 依赖于 Numpy.NET 和 pythonnet_netstandard 包。 如果它们没有安装,让我们继续安装它们。
重要的是要指出,Keras.NET 需要在您的操作系统中安装 Python 2.7-3.7 版本。 它还需要安装 Python 库 Numpy 和 TensorFlow。 在此示例中,我们使用了 Python 3.7 64 位。
如果您在执行本文中的代码时遇到任何问题,请尝试在 ConsoleApplication 中执行 main 方法时在开始时运行以下代码一次。 此代码将设置您需要的环境变量,以便找到所有 DLL
private static void SetupPyEnv()
{
string envPythonHome = @"C:\Users\arnal\AppData\Local\Programs\Python\Python37\";
string envPythonLib = envPythonHome + "Lib\\;" + envPythonHome + @"Lib\site-packages\";
Environment.SetEnvironmentVariable("PYTHONHOME", envPythonHome, EnvironmentVariableTarget.Process);
Environment.SetEnvironmentVariable("PATH", envPythonHome + ";" + envPythonLib + ";" + Environment.GetEnvironmentVariable("PATH", EnvironmentVariableTarget.Machine), EnvironmentVariableTarget.Process);
Environment.SetEnvironmentVariable("PYTHONPATH", envPythonLib, EnvironmentVariableTarget.User);
PythonEngine.PythonHome = envPythonHome;
PythonEngine.PythonPath = Environment.GetEnvironmentVariable("PYTHONPATH");
}
现在我们将看到使用 Keras.NET 创建用于硬币识别的 CNN 是多么容易和透明。 以下类显示了包含模型所有逻辑的 Cnn
类。
public class Cnn
{
private DataSet _dataset;
private Sequential _model;
public Cnn(DataSet dataset)
{
_dataset = dataset;
_model = new Sequential();
}
public void Train()
{
// Build CNN model
_model.Add(new Conv2D(32, kernel_size: (3, 3).ToTuple(),
padding: Settings.PaddingMode,
input_shape: new Shape(Settings.ImgWidth, Settings.ImgHeight, Settings.Channels)));
_model.Add(new Activation(Settings.ActivationFunction));
_model.Add(new Conv2D(32, (3, 3).ToTuple()));
_model.Add(new Activation(Settings.ActivationFunction));
_model.Add(new MaxPooling2D(pool_size: (2, 2).ToTuple()));
_model.Add(new Dropout(0.25));
_model.Add(new Conv2D(64, kernel_size: (3, 3).ToTuple(),
padding: Settings.PaddingMode));
_model.Add(new Activation(Settings.ActivationFunction));
_model.Add(new Conv2D(64, (3, 3).ToTuple()));
_model.Add(new Activation(Settings.ActivationFunction));
_model.Add(new MaxPooling2D(pool_size: (2, 2).ToTuple()));
_model.Add(new Dropout(0.25));
_model.Add(new Flatten());
_model.Add(new Dense(Settings.FullyConnectedNodes));
_model.Add(new Activation(Settings.ActivationFunction));
_model.Add(new Dropout(0.5));
_model.Add(new Dense(_dataset.NumberClasses));
_model.Add(new Softmax());
_model.Compile(loss: Settings.LossFunction,
optimizer: Settings.Optimizer,
metrics: new string[] { Settings.Accuracy });
_model.Fit(_dataset.TrainX, _dataset.TrainY,
batch_size: Settings.BatchSize,
epochs: Settings.Epochs,
validation_data: new NDarray[] { _dataset.ValidationX, _dataset.ValidationY });
var score = _model.Evaluate(_dataset.ValidationX, _dataset.ValidationY, verbose: 0);
Console.WriteLine("Test loss:" + score[0]);
Console.WriteLine("Test accuracy:" + score[1]);
}
public NDarray Predict(string imgPath)
{
NDarray x = Utils.Normalize(imgPath);
x = x.reshape(1, x.shape[0], x.shape[1], x.shape[2]);
return _model.Predict(x);
}
}
我们可以看到,我们首先有一个构造函数,我们在其中接收数据集(在本系列的第二篇文章中导入和处理),并创建存储在私有变量 _model
中的 Sequential
类的新实例。 什么是 Sequential
? 它是一个空模型,使我们能够堆叠图层,这正是我们需要的。
然后,在 Train
方法中,我们首先按照上一篇文章中介绍的架构创建我们的图层堆栈,然后编译模型并调用 fit
方法开始训练。 使用的损失函数是 categorical_crossentropy
。 什么是损失函数? 它是我们用来优化学习过程的函数,也就是说,我们要么最小化它,要么最大化它。 负责最小化损失函数的是优化器——一种改变网络的权重和学习率以最小化损失的算法。
最后,使用验证数据集评估模型。 另一种方法是 Predict
,顾名思义,它预测新传入数据的标签。 此方法应在训练完成后调用。 启动训练短语非常简单,只需运行以下操作即可
var cnn = new Cnn(dataSet);
cnn.Train();
让我们看看在本系列中我们正在经历的硬币识别问题中,在训练期间获得的结果
我们可以看到,我们在训练期间能够达到 100% 的准确率。
对于预测方法,其输出将是一个 NDarray
,其中包含对象或图像属于用于训练 CNN 的其中一个类的概率。
那么,什么样的架构需要 GPU 而不是 CPU 呢? 例如,AlexNet 架构包括五个卷积层和三个完全连接的层,以及池化层和激活层。 由于其复杂性,这种类型的深度 CNN 在 GPU 上表现更好。 一般规则是,您添加的图层越多,权重的计算就越复杂。
在了解了如何编写自己的 CNN 之后,我们将进入预训练模型的领域。 更多相关内容请参见下一篇文章!