本站内容均来自兴趣收集,如不慎侵害的您的相关权益,请留言告知,我们将尽快删除.谢谢.
一、实现自带数据的神经网络
放在这个示例的理解:获得dataset数据–>利用加载器进行数据加载–>设计神经网络的结构–>定义优化器以及损失函数–>遍历数据进行梯度下降求解50次–>用模型进行预测得到预测值
通用理解:数据加载–>设计网络结构–>遍历数据进行梯度下降求解到损失值的最小值或者指定次数–>保存对应的梯度参数或者直接计算test情况
通过pytorch设计网络结构,需要完成以下几点:
- 定义网络结构,初始化函数init
- 定义网络节点连接方式forward函数
1. 获得dataset数据
通过从内置的数据集中获取数据,和之前的方式一样,只不过内置的给你写好了torchvision.datasets.mnist.MNIST.py,以下解释相关变量的定义
解释torchvision.datasets.mnist.MNIST.init.data相关定义以及是怎幺来的
test_data = torchvision.datasets.MNIST('./mnist',train=False) # test_x= Variable(torch.unsqueeze(test_data.test_data,dim=1),volatile=True).type(torch.FloatTensor)[:2000]/255. # 压缩纬度,将第一个纬度给压没了(可以理解为x的纬度) test_x = torch.unsqueeze(test_data.data, dim=1).type(torch.FloatTensor)[:2000] / 255. #取前2000个数据
对于这里面的 test_data.data
的理解, torchvision.datasets.mnist.MNIST.__init__.data
可以看他们的调用关系,它其实是通过MNIST类的__init__进行对象的建立,所以获得的是最终的对象,如下所示:
对象=torchvision.datasets.mnist.MNIST.__init__() 对象具有data属性,所以就可以调用对象.data 综合起来就是: torchvision.datasets.mnist.MNIST.__init__.data
在python的类只要函数里面调用了 self.属性=相关定义赋值
,那幺之后python的类就具有这样的功能。
之所以要进行维度的拓展就是因为cnn的输入是 1*28*28
,所以数据需要转换为 batch_size*1*28*28
,而扩展纬度就是通过unsqueeze,而有时候需要进行维度的统一就是通过unsqueeze以及expand,所以下面对unsqueeze以及expand的使用方法进行探究
unsqueeze可以增加一个纬度,但是维度的siz只是1而已,而expand就可以将数据进行复制,将数据变为n
import torch # 获得一开始的初始化数值:tensor([[a1,a2,a3]]) nn1=torch.rand(1,3) print(nn1) # unsqueeze是解压的意思,在第i个维度上进行扩展,将其扩展为tensor([[[a1,a2,a3]]]) nn1=nn1.unsqueeze(0) print("*"*100) print(nn1) #利用expand对数据进行扩展 nn1=nn1.expand(1,3,3) print("*"*100) print(nn1)
2. 利用加载器进行数据加载
分为训练数据以及测试,由于训练数据需要分批次以及打乱操作等。所以加载方式会有所不同,或者可以可以测试数据的加载更加简单粗暴一些:
- 训练集数据的加载:通过dataset加载数据集–>将数据集加载进加载器中(加载中可以设置一批次迭代的次数还有是否打乱)
- 测试集数据的加载:可以直接加载数据以及对应的目标值就行
# 1. 训练数据的加载 train_data=torchvision.datasets.MNIST( root='./mnist', train=True, transform=torchvision.transforms.ToTensor(),#从下载数据改变数据形式 #(0,1) (0,255) download=DOWNLOAD_MNIST ) train_loader=Data.DataLoader(dataset=train_data,batch_size=BATCH_SIZE,shuffle=True,num_workers=0) # 2. 测试数据的加载 #test不用像train一样分批次加载,同时也不用需要打乱,所以直接获得相关数据就行 test_data = torchvision.datasets.MNIST('./mnist',train=False) # 压缩纬度,将第一个纬度给压没了(可以理解为x的纬度) test_x = torch.unsqueeze(test_data.data, dim=1).type(torch.FloatTensor)[:2000] / 255. #取前2000个数据 转换为batch_size*1*28*28 test_y=test_data.targets[:2000]
3. 设计神经网络的结构
将神经网络中核心函数 init()
以及 forward()
函数实现就行
init() forward()
class CNN(nn.Module): def __init__(self): super(CNN, self).__init__() self.conv1=nn.Sequential( nn.Conv2d(#(1*28*28) #这里的1表示通道 in_channels=1, out_channels=16, kernel_size=5, stride=1, padding=2, #如果 stride=1,padding=(kernel_size-1)/2=(5-1)/2 ),# -->(16,28*28) nn.ReLU(),# -->(16,28*28) nn.MaxPool2d(kernel_size=2),# -->(16,14*14) ) self.conv2=nn.Sequential(# (16,14*14) nn.Conv2d(16,32,5,1,2),#加工32层-->(32 14*14) nn.ReLU(),#-->(32 14*14) nn.MaxPool2d(2),#-->(32 7*7) ) self.out=nn.Linear(32*7*7,10) #把前面的纬度32*7*7变成10 def forward(self,x): x=self.conv1(x) x=self.conv2(x) #(batch, 32 ,7,7) x=x.view(x.size(0),-1) #(batch,32*7*7) output=self.out(x) return output
4. 定义优化器以及损失函数
optimizer = torch.optim.Adam(cnn.parameters(),lr=LR) #Adam是梯度下降的一种方法,将神经网络的参数以及传播率传进去 print(cnn.parameters()) loss_func = nn.CrossEntropyLoss() #损失函数的定义
5. 遍历数据进行梯度下降
梯度下降+每到50次进行相关信息的输出或者一些处理
梯度下降
loss = loss_func(output, y) optimizer.zero_grad() loss.backward() optimizer.step()
批量输出相关信息或者批量处理数据
批量处理数据,也就是epoch=50,这里没有设置相关的变量而是用 if step % 50 == 0:#表示已经进行了50的倍数了
进行判断了,并且这里只做了相关的输出,并没有其他的操作(比如有时候可以对方差做一个汇总使得信息的整体性更强)
for epoch in range(EPOCH): for step, (x, y) in enumerate(train_loader): # 50*10 最后输出是分类的概率大小 output = cnn(x) # 得到网络中的输出数据 loss = loss_func(output, y) # 计算每一个网络的损失值 optimizer.zero_grad() # 在下一次求导之前将保留的grad清空 loss.backward() # 反向传播,计算梯度 optimizer.step() # 应用求导到优化器上去 if step % 50 == 0:#表示已经进行了50的倍数了 test_output = cnn(test_x) # 在分类问题中,通常需要使用max()函数对softmax函数的输出值进行操作,求出预测值索引,然后与标签进行比对,计算准确率。其中1表示纬度 # 函数会返回两个tensor,第一个tensor是每行的最大值;第二个tensor是每行最大值的索引。我们需要的是第二个的索引,本来是tensor的格式,这里需要化为numpy格式 pred_y = torch.max(test_output, 1)[1].data.numpy() # size()考虑到可能大小也是有纬度的,所以取的是第一个纬度 # 这里的loss.data.numpy()和accuracy都是一纬的,如果是数组就直接把数据给输出了,这里也是可以的 accuracy = sum(pred_y == test_y.data.numpy()) / test_y.size(0) print('Epoch: ', epoch, '| train loss: %.4f' % loss.data.numpy(), '| test accuracy: %.2f' % accuracy)
6. 用模型进行预测得到预测值
torch.max的使用见:https://blog.csdn.net/weixin_42295969/article/details/126352240?csdn_share_tail=%7B%22type%22%3A%22blog%22%2C%22rType%22%3A%22article%22%2C%22rId%22%3A%22126352240%22%2C%22source%22%3A%22weixin_42295969%22%7D
# 从测试数据中计算10个预测,[:10]表示列表中第一项到第10项 test_output = cnn(test_x[:10]) # 这里为什幺是max从而获得预测值 pred_y = torch.max(test_output, 1)[1].data.numpy() #返回的是最大值的索引,最大的概率值 print(pred_y, 'prediction number') print(test_y[:10].numpy(), 'real number')
Be First to Comment