共计 5204 个字符,预计需要花费 14 分钟才能阅读完成。
在本文中,咱们将钻研一个卷积神经网络来解决硬币辨认问题,并且咱们将在 Keras.NET 中实现一个卷积神经网络。
在这里,咱们将介绍卷积神经网络(CNN),并提出一个 CNN 的架构,咱们将训练它来辨认硬币。
什么是 CNN? 正如咱们在本系列的前一篇文章中提到的,CNN 是一类常常用于图像分类工作的神经网络(NN),比方物体和人脸识别。在 CNN 中,并非每个节点都连贯到下一层的所有节点。这种局部连通性有助于避免在齐全连贯的网络神经网络中呈现的过拟合问题,并且减速了神经网络的收敛速度。
围绕 CNN 的外围概念是一种被称为卷积的数学运算,卷积在数字信号处理畛域十分常见。卷积被定义为两个函数的乘积,产生的第三个函数示意前两个函数之间的重叠量。
在物体辨认中,卷积操作容许咱们检测图像中的不同特色,如垂直和程度的边缘,纹理和曲线。这就是为什么任何 CNN 的第一层都是卷积层。
CNN 中另一个常见的层是池化层。池化用于缩小图像示意的大小,这意味着缩小参数的数量,并最终缩小计算量。最常见的池化类型是最大池化,它在每个地位上从匹配的单元格组中获取最大值。最初,依据所取得的最大值建设新的图像。
另一个与卷积相干的概念是填充。填充保障了卷积过程将平均地产生在整个图像,包含边界像素。这个保障是由一个零像素的边框反对的,该边框在放大后的图像四周增加(在池化之后),以便能够以雷同的次数拜访图像的所有像素。
最常见的 CNN 架构通常从卷积层开始,接着是激活层,而后是池化层,最初是传统的全连贯网络,比方多层 NN。这种类型的模型是层次化的,称为程序模型。为什么以一个齐全连贯的网络完结? 为了学习转换后图像 (通过卷积和池化) 中的特色的非线性组合。
上面是咱们将在 CNN 中实现的架构:
- Conv2D 层 - 32 个过滤器,过滤器大小为 3
- 激活层应用 ReLU 函数
- Conv2D 层 - 32 个过滤器,过滤器大小为 3
- 激活层应用 ReLU 函数
- MaxPooling2D 层 - 利用 (2,2) 池窗口
- DropOut 图层,25% - 通过随机删除前一层的一些值来避免过拟合(设置为 0); 也就是浓缩法
- Conv2D 层 - 64 个过滤器,过滤器大小为 3
- 激活层应用 ReLU 函数
- Conv2D 图层 - 64 个过滤器,过滤器大小为 3,步幅为 3
- 激活层应用 ReLU 函数
- MaxPooling2D 层 - 利用 (2,2) 池窗口
- DropOut 层,25%
- Flatten 层 - 转换数据,以在下一层中应用
- Dense 层——示意具备 512 个节点的传统神经网络的全连贯。
- 激活层应用 ReLU 函数
- DropOut 层,在 50%
- Dense 层,与节点数量匹配的类的数量
- Softmax 层
该体系结构遵循了一种用于物体辨认的 CNN 体系结构模式; 层参数通过试验进行了微调。
咱们通过的参数微调过程的后果局部存储在 Settings 类中,咱们在这里展现:
public class Settings
{
public const int ImgWidth = 64;
public const int ImgHeight = 64;
public const int MaxValue = 255;
public const int MinValue = 0;
public const int Channels = 3;
public const int BatchSize = 12;
public const int Epochs = 10;
public const int FullyConnectedNodes = 512;
public const string LossFunction = "categorical_crossentropy";
public const string Accuracy = "accuracy";
public const string ActivationFunction = "relu";
public const string PaddingMode = "same";
public static StringOrInstance Optimizer = new RMSprop(lr: Lr, decay: Decay);
private const float Lr = 0.0001f;
private const float Decay = 1e-6f;
}
咱们当初有了 CNN 的体系结构。接下来,咱们将钻研应用 Keras.NET 实现的用于硬币辨认的 CNN。
首先,让咱们从 Nuget 包管理器下载 Keras.NET 包。咱们能够在 Tools > Nuget package manager 中找到 Nuget 包管理器。Keras.NET 依赖于包 Numpy.NET 和 pythonnet_netstandard。如果没有装置它们,让咱们持续装置它们。
须要指出的是,Keras.NET 须要在你的操作系统中装置 Python 2.7-3.7 版本。它还须要装置 Python 库 Numpy 和 TensorFlow。在本例中,咱们应用的是 64 位的 Python 3.7。
如果在执行本文中的代码时遇到任何问题,请在控制台应用程序中主办法的开始执行时尝试运行以下代码一次。这段代码将设置所需的环境变量,以便找到所有 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);
}
}
如咱们所见,咱们首先有一个构造函数,用于接收数据集(在本系列的第二篇文章中导入和解决),并创立 Sequential 类的新实例存储在公有变量_model 中。Sequential 是什么? 这是一个空模型,它给了咱们叠加档次的可能性,而这正是咱们所须要的。
而后,在 Train 办法中,咱们首先依照上一篇文章中介绍的架构创立咱们的层堆栈,而后编译模型并调用 fit 办法开始训练。应用的损失函数是 categorical_crossentropy。什么是损失函数? 它是咱们用来优化学习过程的函数,也就是说,咱们要么最小化它,要么最大化它。负责最小化损失函数的是优化器——一种通过扭转网络的权重和学习率来最小化损失的算法。
最初,利用验证数据集对模型进行评估。另一个办法是 Predict,顾名思义,它预测新输出数据的标签。训练完结后,应调用此办法。开始训练阶段就像运行以下代码一样简略:
var cnn = new Cnn(dataSet);
cnn.Train();
让咱们来看看在这个系列中咱们正在经验的硬币辨认问题的训练中所取得的后果:
咱们能够看到,在训练过程中,咱们可能达到 100% 的准确率。在 prediction 办法中,它的输入将是一个 NDarray,它蕴含了物体或图像属于 CNN 某个类的概率。
那么,什么样的架构须要 GPU 而不是 CPU 呢? 例如,AlexNet 体系结构包含 5 个卷积层和 3 个齐全连贯的层,以及池化和激活层。这种类型的深度 CNN 因为其复杂性,在 GPU 上体现得更好。个别的规定是,你增加的层越多,权重的计算就会越简单。
在理解了如何编写本人的 CNN 之后,咱们将进入预训练模型的畛域。下一篇文章将具体介绍这一点!
欢送关注我的公众号,如果你有喜爱的外文技术文章,能够通过公众号留言举荐给我。