想起了自己关于pytorch的学习路线。一开始找了各种资料,自己也能写下来,但是没有亲身体验学习的过程。一些教程从编写CNN开始。虽然内容其实很简单,但是如果直接上手,很容易让人注意力不集中,学得一头雾水。有些教程有点太多了。大师走到门槛的时候,总觉得还没进门教程就结束了。所以我总结了我原来的学习路线,准备继续巩固我的pytorch基础;另一方面,我也想从头整理一个教程,从我没接触过pytorch开始,整理最新论文中的一些工作。以自己的学习笔记为主线,可以参考。在第一个笔记中,我们先完成一个简单的分类器。主要流程分为以下三个部分:1.自定义一个训练集,具体是二维平面上的一些点,分为两类;2.构建浅层神经网络实现特征拟合。主要是了解pytorch中如何搭建网络结构;3.完成训练和测试部分工作,熟悉pytorch如何训练和测试网络。1.自定义生成的数据集n_data=torch.ones(100,2)x0=torch.normal(2*n_data,1)y0=torch.zeros(100)x1=torch.normal(-2*n_data,1)y1=torch.ones(100)x=torch.cat((x0,x1)).type(torch.FloatTensor)y=torch.cat((y0,y1)).type(torch.LongTensor)在本文中我们首先考虑在自己定义的简单数据集上实现分类,这样最容易理解如何用pytorch搭建神经网络模型。熟悉numpy的同学应该能猜到这段代码的内容,不过在numpy中是一个numpy数组,在pytorch中是一个tensor。这里我就简单介绍下这几行代码的作用,给有需要的同学理顺一下思路。首先,n_data是基准数据,用于生成其他数据。内容是一个100行2列的张量,里面的值都是1。x0是一类数据的坐标值,通过这个n_data生成。具体的生成方法是使用torch.normal()函数,第一个参数是mean,第二个参数是std。所以返回的结果x0和n_data是一样的shape,但是里面的数据是随机抽取的,服从均值为2,标准差为1的正态分布。y0是一个100维的张量,其值全为0.我们可以这样理解x0和y0。x0的形状是一个100行2列的张量。里面的值随机分布在2左右,符合正态分布。我们将这些点的标签设置为y0,即0。而x1对应的中心为-2,标签为y1,即每个点的标签为1。最终生成的x和y是将所有数据,x0和x1合并为数据,y0和y1合并为标签。2.构建一个浅层神经网络)self.out=torch.nn.Linear(n_hidden,n_output)defforward(self,x_layer):x_layer=torch.relu(self.n_hidden(x_layer))x_layer=self.out(x_layer)x_layer=torch.nn。functional.softmax(x_layer)返回x_layernet=Net(n_feature=2,n_hidden=10,n_output=2)#print(net)optimizer=torch.optim.SGD(net.parameters(),lr=0.02)loss_func=torch.nn上面的Net()类.CrossEntropyLoss()是如何构建神经网络的。如果我们是第一次用pytorch编写神经网络,那么这是一个足够简单的示例。内容由两部分组成,分别是__init__()函数和forward()函数。你可以这样简单理解:__init__()函数定义了网络结构,它有哪些层,每一层有什么功能。比如这个函数中,self.n_hidden定义了一个线性拟合函数,即全连接层,相当于映射到一个隐藏层。输入为n_feature,输出为隐藏层神经元个数n_hidden。那么self.out也是一个全连接层,输入是刚才隐藏层的神经元个数n_hidden,输出是最终的输出结果n_output。然后是forward()函数,相当于定义了我们神经网络的执行顺序。所以这里可以看到上面的隐藏层函数是先在输入x_layer上执行的,也就是先全连接的self.n_hidden(),然后在输出上执行激活函数relu。接下来以同样的方式进行,经过一个输出层self.out()得到最终的输出。然后返回输出x_layer。优化器是这里定义的优化方法,其中lr是学习率的参数。然后损失函数我们选择交叉熵损失函数,也就是上面最后一行代码。对于优化算法和损失函数,可以直接在pytorch中选择不同的api接口,形式上直接参考上面的固定形式。3.完成iinrange(100)的训练和测试:out=net(x)#print(out.shape,y.shape)loss=loss_func(out,y)optimizer.zero_grad()loss.backward()optimizer.step()接下来我们看看如何训练这个过程。net()是我们从Net()类实例化出来的一个对象,所以我们可以直接使用net()来完成模型的运算,out是模型预测的结果,loss是根据交叉熵计算的具有实值误差的损失函数。以下三行代码是如何进行梯度反向传播的标准形式。至此,我们的训练已经完成,现在可以直接使用这个网络对测试数据集进行预测和分类。#trainresulttrain_result=net(x)#print(train_result.shape)train_predict=torch.max(train_result,1)[1]plt.scatter(x.data.numpy()[:,0],x.data.numpy()[:,1],c=train_predict.data.numpy(),s=100,lw=0,cmap='RdYlGn')plt.show()为了让大家更好的理解这个模型的作用,这里我们来做一些可视化工作,看看模型学习得如何。这个目标可以通过python中非常常用的数据可视化库matplotlib来实现,matplotlib的具体用法就不介绍了。这里的作用是展示训练好的模型在训练集上的分类效果,可以理解为训练误差。#testt_data=torch.zeros(100,2)test_data=torch.normal(t_data,5)test_result=net(test_data)prediction=torch.max(test_result,1)[1]plt.scatter(test_data[:,0],test_data[:,1],s=100,c=prediction.data.numpy(),lw=0,cmap='RdYlGn')plt.show()然后我们随机生成一些以0为均值的数据,到查看模型如何对这些数据点进行分类。虽然没有画出训练好的分割线,但是我们也可以看出模型学习了一个分割接口,将数据分为两类。
