基于PyTorch实现最基本的神经网络

        笔者在尝试使用库实现各种神经网络时,发现网络上大部分的教程都是使用Tensorflow或者是Kears,虽然也有PyTorch,但是比较少,而且教程都过于老旧,有一大部分是直接上来就实现一个卷积神经网络,并不是我想知道的,我想要的只是最简单的模型,具体要怎么操作我自己再改嘛,我是来学习的不是来看你秀技的,最终,在查阅资料与询问大佬后实现了一个最简单的神经网络,准确率有99%,当然这是这训练集上的准确率,测试集还没有试过,因为只是最简单的实现,这些内容也等构建出来再说。

        首先描述一下神经网络的结构,只有三层,一层输入层,一层隐藏层,一层输出层,然后每个层之间则是完全相互连通的,输入数据为经典的手写数字识别,具体数据可以在sklearn直接导入,如下所示。

        差点忘记了,神经网络与普通的机器学习模型不一样,它是直接可以多分类的,也就是说输出层的数据就是属于哪一类的意思,它是[1,0,0,0,0,...]这样的,当然不同激活函数结果不一样,我只是说明一下过程。因此,你输入的标签是需要转成one-hot编码的,也就是把原来,比如手写数字,标签是0,转成[1,0,0,0,0,0,0,0,0,0],标签是1则是,[0,1,0,0,0,0,0,0,0,0],以此类推,如果是DataFrame格式的话就是直接,y = pd.get_dummies(y).values。

下面介绍如何使用PyTorch构建神经网络(虽然说是PyTorch,但是导入的时候用的是torch):

 构建方面,代码如下所示:

class MyNN(torch.nn.Module):
    def __init__(self, input_size, hidden_size, output_size):
        super(MyNN, self).__init__()
        self.linear1 = torch.nn.Linear(input_size, hidden_size)
        self.linear2 = torch.nn.Linear(hidden_size, output_size)
        self.relu = torch.nn.ReLU()
        self.sigmoid = torch.nn.Sigmoid()

    def forward(self, x):
        out = self.linear1(x)
        out = self.sigmoid(out)
        out = self.linear2(out)
        out = self.sigmoid(out)
        return out

        MyNN这个类就是神经网络的结构,细节的语法可以不用管,估计可以理解成给普通的类打了torch库的补丁,下面对各个函数的内容进行解释: 

对__init__函数,参数字如其名:

        其中self.linear1,self.linear2分别表示输入到隐藏与隐藏到输出层的参数,relu与sigmoid应该是激活函数,具体可以根据结果继续更换,事实上也可以直接用torch的F模块直接导出相应的函数,具体可以自行学习。

对forward函数:

        没什么参数,可以理解成把数据代入至各个层进行计算,得到预测结果,也就是前向传播的过程,输出就是out,如果到后面复杂使用需要增加层数的话就需要调整计算再加进去,方法类似于上面的,这个不属于本文涉及的范围,不展开。

        在构建了神经网络类之后,构建神经网络类,很简单:

model = MyNN(64, 100, 10)

        首先是输入层的结点数,也就是你要训练的数据的维数,那么在对sklearn的手写数字进行拆包后发现它的维度是64,而隐藏层设置了100,这个是随便设置的,由于只是一个例子没有对它的取值做过多的思考,取不同的值对模型的准确率有较大的影响,最后的10是输出层,因为是手写数字识别,就是0,1,...,9,也就是十个标签,所以输出层是十个结点。

        如果完成了上面的操作,恭喜你,你已经完成了最基本的神经网络的构建,接下来要开始训练模型了,代码如下所示。

criterion = torch.nn.MSELoss()
optimizer = torch.optim.SGD(model.parameters(), lr=1)

X = torch.from_numpy(X).float()
y = torch.from_numpy(y).float()

for epoch in range(5000):
    optimizer.zero_grad()
    y_pred = model(X)
    loss = criterion(y_pred, y)
    loss.backward()
    optimizer.step()

        第一个是损失函数,第二个是优化器,具体就直接这么写就行了,而至于optimizer中有多个优化函数,一个是直接SGD,或者是Adam等等,而lr表示学习率,一般最大是1,普遍来说,学习率越低达到最优解所需的迭代次数越高。

        接下来很重要,注意,如果是直接从pd.DataFrame格式导入的,不要直接使用torch.tensor(),最好是先把数据转为numpy格式后再变为tensor()格式,如何导入也是使用torch.from_numpy()即可,而且由于硬性要求,数据类型需要相同,这里设置成float,即浮点数。

        剩下就是循环训练了,数学原理是求偏导,首先使用optimizer.zero_grad(),将偏导设置为0,接下来计算当前模型的预测与目标值的差异,也就是损失函数,最后根据损失函数进行反向传播,然后更新参数,就是这么多(想到当时手工实现写了一大堆,这里几句就实现了,多少有点难受)。一般这个过程要比较久,如果怕没有结果的可以输出一下loss,直接再loss.backward()前面加个print(loss)或者直接print(epoch)就可以知道运行到哪一步了。

        那么在完成上述所有操作后,你已经完整的训练完一个神经网络模型了,可喜可贺可喜可贺。接下来则是如何计算准确率的问题,很简单,也是直接调用库即可。

        具体代码如下所示:

from sklearn.metrics import accuracy_score

y_pred = model(X)
y_pred = y_pred.detach().numpy()
y_pred = np.argmax(y_pred, axis=1)

print(accuracy_score(y_pred, load_digits().target))

        没什么好解释的,就是直接调用库算准确率,结果是99%,当然和我最开始说的一样,这个玩意的准确率说的是在训练集上面的准确率,意思是把这个跑出来的模型,丢用来训练的数据进去看他效果如何,不是说它在测试集上的表现。

使用PyTorch构建最简单的神经网络的所有代码如下所示:

import torch
from sklearn.metrics import accuracy_score
from sklearn.datasets import load_digits
import numpy as np
import pandas as pd

X = load_digits().data
y = load_digits().target
#将y转换为one-hot编码
y = pd.get_dummies(y).values

class MyNN(torch.nn.Module):
    def __init__(self, input_size, hidden_size, output_size):
        super(MyNN, self).__init__()
        self.linear1 = torch.nn.Linear(input_size, hidden_size)
        self.linear2 = torch.nn.Linear(hidden_size, output_size)
        self.relu = torch.nn.ReLU()
        self.sigmoid = torch.nn.Sigmoid()

    def forward(self, x):
        out = self.linear1(x)
        out = self.sigmoid(out)
        out = self.linear2(out)
        out = self.sigmoid(out)

        return out
    
model = MyNN(64, 100, 10)

criterion = torch.nn.MSELoss()
optimizer = torch.optim.SGD(model.parameters(), lr=1)

X = torch.from_numpy(X).float()
y = torch.from_numpy(y).float()

for epoch in range(5000):
    optimizer.zero_grad()
    y_pred = model(X)
    loss = criterion(y_pred, y)
    loss.backward()
    optimizer.step()

from sklearn.metrics import accuracy_score

y_pred = model(X)
y_pred = y_pred.detach().numpy()
y_pred = np.argmax(y_pred, axis=1)

print(accuracy_score(y_pred, load_digits().target))

以此为基础,我也做了一个手写字母识别的,准确率是97%:

import torch
import torch.nn as nn
import torch.nn.functional as F
import pandas as pd

#将数据转为tensor
data = pd.read_csv("all_alphas.csv")
data = data[data.iloc[:, -1].isin(["A", "B", "C", "D", "E", "F", "G", "H", "I", "J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X", "Y", "Z"])]
x = data.iloc[:,:-1].values
y= data.iloc[:,-1]
y = pd.get_dummies(y)

x = torch.from_numpy(x).float()
y = torch.from_numpy(y.values).float()

class Net(nn.Module):

    def __init__(self, input_size, hidden_size, output_size):
        super(Net, self).__init__()
        self.linear1 = torch.nn.Linear(input_size, hidden_size)
        self.linear2 = torch.nn.Linear(hidden_size, output_size)
        self.relu = torch.nn.ReLU()
        self.sigmoid = torch.nn.Sigmoid()

    def forward(self, x):
        out = self.linear1(x)
        out = self.sigmoid(out)
        out = self.linear2(out)
        out = self.sigmoid(out)

        return out

net = Net(100,100,26)

optimizer = torch.optim.SGD(net.parameters(),lr = 1)
loss_func = torch.nn.MSELoss()


for t in range(5000):
    prediction = net.forward(x)
    loss = loss_func(prediction,y)
    optimizer.zero_grad()
    loss.backward()
    optimizer.step()

#准确率
prediction = net(x)
pred = torch.argmax(prediction,1)
y = torch.argmax(y,1)
correct = torch.eq(pred,y)
correct = correct.sum().float()
accuracy = correct/len(y)
print("accuracy:",accuracy)

        以上的代码的灵感来源于Z与某篇在知乎上找到的文章,具体网页找不到了,是讲怎么构建二维的神经网络的,代码也放上来,直接搞个py文件跑一下效果很好看。

import torch
import torch.nn as nn
import torch.nn.functional as F
import matplotlib.pyplot as plt
from torch.autograd import Variable

x = torch.unsqueeze(torch.linspace(-1,1,100),dim=1)
y = x.pow(3)+0.1*torch.randn(x.size())

x , y =(Variable(x),Variable(y))

# plt.scatter(x,y)
# plt.scatter(x.data,y.data)
# plt.scatter(x.data.numpy(),y.data.numpy())
# plt.show()

class Net(nn.Module):
    def __init__(self,n_input,n_hidden,n_output):
        super(Net,self).__init__()
        self.hidden1 = nn.Linear(n_input,n_hidden)
        self.hidden2 = nn.Linear(n_hidden,n_hidden)
        self.predict = nn.Linear(n_hidden,n_output)
    def forward(self,input):
        out = self.hidden1(input)
        out = F.relu(out)
        out = self.hidden2(out)
        out = F.sigmoid(out)
        out =self.predict(out)

        return out

net = Net(1,20,1)
print(net)

optimizer = torch.optim.SGD(net.parameters(),lr = 0.1)
loss_func = torch.nn.MSELoss()

plt.ion()
plt.show()

for t in range(5000):
    prediction = net(x)
    loss = loss_func(prediction,y)

    optimizer.zero_grad()
    loss.backward()
    optimizer.step()

    if t%50 ==0:
        plt.cla()
        plt.scatter(x.data.numpy(), y.data.numpy())
        plt.plot(x.data.numpy(), prediction.data.numpy(), 'r-', lw=5)
        plt.text(0.5, 0, 'Loss = %.4f' % loss.data, fontdict={'size': 20, 'color': 'red'})
        plt.pause(0.05)

plt.ioff()
plt.show()

有任何疑问或交流欢迎联系我的邮箱或者直接评论:

okura_machi@126.com

  • 27
    点赞
  • 34
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值