在这里,我们介绍了上一篇文章中介绍的体系结构的代码,并且我们将研究另一种体系结构,该体系结构需要比普通的CPU更多的知识来进行准确的训练。
首先,让我们从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);
}
}
如我们所见,我们首先有一个构造函数,用于接收数据集(在本系列的第二篇文章中导入和处理),并创建存储在private变量中的Sequential类的新实例_model。什么Sequential? 它是一个空模型,使我们有可能堆叠图层,而这正是我们所需要的。
然后,在Train方法中,我们首先按照上一篇文章中介绍的体系结构中的描述创建层堆栈,然后编译模型并调用fit方法以开始训练。使用的损失函数为categorical_crossentropy。什么是损失函数?它是我们用来优化学习过程的函数,也就是说,我们将其最小化或最大化。最小化损失函数的负责人是优化器,它是一种算法,它可以改变网络的权重和学习率,以最大程度地减少损失。
最后,使用验证数据集评估模型。另一个方法是Predict,顾名思义,它可以预测新传入数据的标签。培训结束后应调用此方法。开始训练短语就像运行以下命令一样简单:
var cnn = new Cnn(dataSet);
cnn.Train();
让我们看看在本系列中我们要解决的硬币识别问题的训练过程中获得的结果:
我们可以看到我们在训练过程中能够达到100%的准确性。
在预测方法的情况下,其输出将是NDarray,其包含对象或图像属于用于训练CNN的类别之一的概率。
那么,什么样的架构会需要GPU而不是CPU?例如,AlexNet体系结构包括五个卷积层和三个完全连接的层,以及池化和激活层。由于其复杂性,这种类型的深度CNN在GPU上的性能更好。一般规则是,添加的图层越多,权重的计算就越复杂。