任务介绍
- 使用numpy手动实现一个前向传播过程
 使用Pytorch搭建一个简单的分类网络,搭配CIFAR-10数据集,完成一个简单物体分类模型的搭建,训练,预测,与评估。
数据集介绍
包含10个类别60000张32*32像素的图片,其中50000张训练集,10000张测试集。
简单神经网络的前向传播
一些小知识
tanh函数
numpy中的点乘与矩阵相乘
点乘:numpy.dot()
一维:计算内积dot(1xn,1xn)——>一个数
二维:dot(nxm.mxn)——>nxn
- 对应元素相乘:Numpy.multiply或“*”
 
三层网络的架构

使用numpy实现神经网络的前向传播过程,并算出输出层的最终输出结果。为了完成上述任务我们需要进行如下假设:
1.输入的值为[3,5]
2.隐藏层h1的两个权重为[2,4]、[4,-5]
3.隐藏层h2的两个权重为[-1,1]、[2,2]
4.输出层的权重为[-3,7]
5.所有层不使用偏置
6.所有隐藏层需添加tanh激活函数
input_data = np.array([3, 5])# 定义数据,作为输入数据input_data = np.array([3, 5])# 定义各个节点权重weights = {'h11': np.array([2, 4]),'h12': np.array([4, -5]),'h21': np.array([-1, 1]),'h22': np.array([2, 2]),'out': np.array([-3, 7])}# 定义tanh激活函数def tanh(x):return (np.exp(x) - np.exp(-x)) / (np.exp(x) + np.exp(-x))# 输入层数据与第一隐层权重相乘、求和,并输入激活函数中hidden_11_value = tanh( (input_data * weights['h11']).sum() )hidden_12_value = tanh( (input_data * weights['h12']).sum() )hidden_1_output = np.array([hidden_11_value, hidden_12_value])# 第一层输出数据与第二层隐层权重相乘、求和,并输入到激活函数hidden_21_value = tanh( (hidden_1_output * weights['h21']).sum() )hidden_22_value = tanh( (hidden_1_output * weights['h22']).sum() )hidden_2_output = np.array([hidden_21_value, hidden_22_value])# 输出层,无激活函数output = (hidden_2_output * weights['out']).sum()print(output)
CIFAR-10图像分类
神经网络训练步骤如下:
1.清空优化器梯度
2.读入data和label
3.运行模型前向传播过程
4.基于模型输出生成最终结果
5.计算损失
6.基于损失计算梯度
7.基于梯度更新参数
outputs = net(inputs) # 模型前向传播loss.backwards() # 用于计算梯度optimizer.step() # 用于参数更新optimizer.zero_grad() # 用于清空优化器梯度inputs,label = data # 用于读取data和labelinputs = inputs.view(-1, 32*32*3) # 用于对输入形状进行变化preds
模型测评过程中的数据导入、前向传播过程与训练过程基本相同。
完整步骤
1.大for循环-epochs,用于管理一套数据循环训练几遍
2.小for循环-step,用于以batchsize为单位,从dataloader中调取数据
3.清空优化器的梯度
4.读入data和label,并进行形状变换(可做可不做)
5.运行模型前向传播过程
6.基于模型输出生成最终结果
7.计算损失
8.基于损失计算梯度
9.基于梯度更新参数
# 基础运算库import numpy as np# 深度学习库import torchimport torch.nn as nnimport torch.optim as optimimport torchvisionimport torch.nn.functional as Fimport torchvision.transforms as transforms# 辅助绘图库import matplotlib.pyplot as plt# 时间操作库import time# 进度条控制库from tqdm import tqdmtransform = transforms.Compose([transforms.ToTensor(),transforms.Normalize((0.49140, 0.48216, 0.44653),(0.24703, 0.24349, 0.26159) )])trainset = torchvision.datasets.CIFAR10(root=r'.', train=True, download=True, transform=transforms)testset = torchvision.datasets.CIFAR10(root='.', train=False, download=True, transform=transforms)trainloader = torch.utils.data.DataLoader(trainset, batch_size=16, shuffle=16)testloader = torch.utils.data.DataLoader(testset, batch_size=16, shuffle=16)print(trainset.classes) # 查看类别# 搭建简单神经网络class Net(nn.Module):def __init__(self):super(Net, self).__init__()self.fc1 = nn.Linear(32*32*3, 1000)self.fc2 = nn.Linear(1000, 500)self.fc3 = nn.Linear(500, 10)def forward(self, x):x = F.relu(self.fc1(x))x = F.relu(self.fc2(x))return self.fc3(x)net = Net()# 定义损失函数criteria = nn.CrossEntropyLoss()# 定义优化器,将神经网络参数传入,并定义学习率optimizer = optim.Adam(net.parameters(), lr=1e-4)# 神经网络训练num_epochs = 10since = time.time()net.train()for epoch in range(num_epochs):print(f"Epoch {epoch + 1}/{num_epochs}")running_loss = 0.0running_correct = 0for data in tqdm(trainloader):# 清空梯度optimizer.zero_grad()inputs, labels = dataoutputs = net(inputs.view(-1, 32*32*3))loss = criteria(outputs, labels)loss.backward()optimizer.step()_, preds = torch.max(outputs, 1)running_loss += loss.item() * inputs.size(0)running_correct += torch.sum(preds == labels)epoch_loss = running_loss / trainloader.dataset.data.shape[0]epoch_acc = running_correct.double() / trainloader.dataset.data.shape[0]print("train loss: {:.4f} Acc: {:.4f}".format(epoch_loss, epoch_acc))print('+++'*10)time_elapsed = time.time() - sinceprint('Training complete in "{:0f}m{:.0f}s'.format(time_elapsed // 60, time_elapsed % 60))# 模型评估correct, total = 0, 0net.eval()for data in tqdm(testloader):inputs, labels = datainputs = inputs.view(-1, 32*32*3)outputs = net(inputs)_, predict = torch.max(outputs, 1)total += labels.size(0)correct += (predict == labels).sum().item()print("The test set accuracy of network is: %d %%" % (100 * correct / total))
可视化查看图片
#把图片进行可视化展示#定义画图的函数def imshow(inp, title=None):"""Imshow for Tensor."""#定义画图的画布fig = plt.figure(figsize=(30, 30))#转换图片的纬度inp = inp.numpy().transpose((1, 2, 0))mean = np.array([0.485, 0.456, 0.406])std = np.array([0.229, 0.224, 0.225])#对图片进行标准化inp = std * inp + mean#整个图片数组的值限制在指定值a_min,与a_max之间inp = np.clip(inp, 0, 1)#对图片进行可视化展示plt.imshow(inp, )# 获取一个batch的数据inputs, classes = next(iter(trainloader))# 以网格的格式展示,作用是将若干幅图像拼成一幅图像out = torchvision.utils.make_grid(inputs)# plt.imshow()就可显示图片同时也显示其格式。imshow(out, title=[trainset.classes[x] for x in classes])
