基于pytorch训练神经网络,实现非线性的分类模型

在平面上,包括了3组不同类别的训练数据,分别使用红色、蓝色和绿色表示。
它们呈非线性的分布方式:

我们要基于Pytorch深度学习框架,训练一个神经网络模型,将这三组数据分开。
并且,我们要将模型产生的分类决策边界,使用橙色进行标记:

分类数据的生成
首先来看分类数据的生成:

定义函数make_data,函数传入num,代表每种类别的数据个数。
在函数中,使用np.random.seed(0),设定随机数生成器的种子,使随机数序列,每次运行时都是确定的。
定义red保存红色数据,数据使用make_blobs生成,它是以(0, 0)为中心的正太分布数据。
定义green保存绿色数据,数据使用make_circles生成,它分布在红色数据的周围。
定义blue保存蓝色数据,数据分布在四个角落。函数返回三种数据。

在main函数中,调用make_data,每种类别生成100个数据。然后创建-4到4的平面画板,并使用plt.scatter绘制出绿色、蓝色和红色三种数据。
神经网络模型的定义
为了解决该分类问题,我们要定义一个三层神经网络。

输入层包括x1和x2两个特征,它们表示平面上,数据点的横坐标和纵坐标。
隐藏层有5个神经元,它们是解决该分类问题的高级特征。
输出层有3个神经元,对应3种不同的类别。
输出层输出的y1、y2、y3,会输入至softmax函数,转换为三种类别的概率,p1、p2和p3。

代码实现如下:

定义神经网络类Network,它继承nn.Module类。
实现类的初始化函数init,函数传入参数n_in, n_hidden, n_out,代表输入层、隐藏层和输出层中的神经元数量。
在init函数中,调用了父类的初始化函数super.init。
然后定义两个线性层layer1和layer2,layer1是输入层与隐藏层之间的线性层,layer2是隐藏层与输出层之间的线性层。
在forward函数中,实现神经网络的前向传播。
函数传入输入数据x,先计算layer1的结果,并进行relu激活,再计算layer2的结果,并返回。
神经网络模型的训练
完成模型的定义后,训练神经网络模型。

定义特征数n_features=2,隐藏层神经元个数,n_hidden=5,类别数n_classes=3。
定义迭代次数n_epochs=10000,学习速率learning_rate=0.001。
然后将绿色、蓝色、红色三种样本,从numpy数组转换为张量形式,一起组成训练数据data。
设置label保存三种样本的标签。
接着创建神经网络模型实例model,交叉熵损失函数CrossEntropyLoss和Adam优化器optimizer。
完成这些必要的变量声明后,进入神经网络的循环迭代。

在循环中,使用当前的模型,预测训练数据data,结果保存在output中。这里即为前向传播。
然后调用criterion,计算预测值output与真实值label之间的损失loss。
调用loss.backward,通过自动微分计算损失函数关于模型参数的梯度。
调用optimizer.step,更新模型参数,使得损失函数减小。调用zero_grad,将梯度清零,以便于下一次迭代。这实际上就是反向传播。
模型的每一轮迭代,有前向传播和反向传播共同组成。

在迭代过程中,每1000次迭代,打印一次当前的损失,共打印10次。
这里loss.item对应损失的标量值。
绘制决策边界
定义draw_decision_boundary函数,生成用于绘制决策边界的等高线数据。

传入的min-x1到max-x1是画板的横轴范围,min-x2到max-x2是画板的纵轴范围。
model是训练好的模型。
在函数中,我们会根据已训练的model,计算对应类别结果,不同类别结果会对应不同的高度,从而基于数据点的坐标与高度数据,绘制等高线。

首先调用mesh-grid生成网格数据点。
每个点的距离是0.02,这样生成的点,可以覆盖平面的全部范围。
然后设置x1s、x2s和z分别表示数据点的横坐标、纵坐标和类别的预测结果。
遍历全部样本,将样本转为张量后,使用model预测结果,选择概率最大的类别,添加到高度z中。

这里相当于将平面上的黑色点,标记为红色、绿色、蓝色三种颜色。
最后将z重新设置为和xx1相同的形式,然后返回xx1、xx2和z。

在main函数的最后,使用函数draw_decision_boundary,生成数据,然后调用plt.contour绘制多分类的决策边界。
运行程序,在结果中可以看到橙色的决策边界。
那么到这里,使用神经网络,训练非线性的分类模型就讲完了,感谢大家的观看,我们下节课再会。