记录热舒适性的预测与推荐的学习
第一篇 从DNN开始探究
1. 选用工具
语言框架:pytorch
之前写深度学习使用的TensorFlow,这次的学习基于pytorch的学习,关于两者之间的区别,稍后有时间可以介绍,这里先留个坑,待之后时间回来填坑。
这里区别可以先参考pytorch和TensorFlow的区别之后有想法可以继续填坑。
2. 代码实现
第一篇我先实现一个简单的DNN代码,使用的数据集则是最经典的Minst,手写数据集。代码是参考pytorch示例:深度神经网络实现,这里我会复现下这里面的代码,可以直接参考我展示的下方代码,链接里会详细介绍了一些优化方法,有兴趣的可以点击去参考。
- 该神经网络结构:1输入层,1全连接的隐含层,1输出层,预期达到98%左右的准确率,下面来进行详细的代码设计,看看效果如何。
- 配置库和配置参数,这一步是动态修改的,在编写代码时用到什么库import就可以
import torch
import torch.nn as nn
import torchvision.datasets as dsets
import torchvision.transforms as transforms
from torch.autograd import Variable
torch.manual_seed(1) # 设置人工种子,保证结果可重复
input_size = 784 # 输入特征的大小,图片为28*28
hidden_size = 500 # 隐藏层为500个神经元
num_classes = 10 # 输出层:10 类,手写数据集为10分类
num_epochs = 5 # 训练参数:训练轮数,根据训练结果可以调节
batch_size = 100 # 参数: 批大小 60000个训练样本要分为600个批次进行
learning_rate = 0.001 # 参数:学习率 一般默认为0.001,根据结果再调整
- 加载数据集,mnist数据集在pytorch中有集成,可以直接使用,放在./data目录中
# 加载数据集
train_dataset = dsets.MNIST(root='./data',
train=True,
transform=transforms.ToTensor(),
download=True)
# load test set
test_dataset = dsets.MNIST(root='./data',
train=False,
transform=transforms.ToTensor())
- 批处理数据
torch.utils.data.DataLoader 函数:【在训练模型时使用到此函数,用来把训练数据分成多个小组,此函数每次抛出一组数据。直至把所有的数据都抛出。就是做一个数据的初始化。】
# 训练集的shuffle必须为True,表示每次从60000训练样本中随机选择100个作为一个批次
train_loader = torch.utils.data.DataLoader(dataset=train_dataset,
batch_size=batch_size,
shuffle=True)
# 测试集的shuffle要为False,即要保证10000个测试样本都只被预测一遍
test_loader = torch.utils.data.DataLoader(dataset=test_dataset,
batch_size=batch_size,
shuffle=False)
- 创建DNN模型,其中使用nn包来创建
# 创建DNN模型
class Net(nn.Module):
def __init__(self, input_size, hidden_size, num_classes):
super(Net, self).__init__()
self.fc1 = nn.Linear(input_size, hidden_size) # 全连接
self.relu == nn.ReLU()
self.fc2 = nn.Linear(hidden_size, num_classes)
def forward(self, x):
out = self.fc1(x) #输入的样本数大小,eg 100个大小为784的图片
out = self.relu(out)
out = self.fc2(out)
return out
net = Net(input_size, hidden_size, num_classes)
print(net)
输出结果为以下情况则表示以上代码顺利执行:
Net(
(fc1): Linear(in_features=784, out_features=500, bias=True)
(relu): ReLU()
(fu2): Linear(in_features=500, out_features=10, bias=True)
)
- 训练模型
enumerate 函数【返回列表元素及下标】
# train model
# 损失函数:交叉损失函数, CrossEntropyLoss
criterion = nn.CrossEntropyLoss()
# 优化: 使用Adam优化器
optimizer = torch.optim.Adam(net.parameters(), lr=learning_rate)
# 训练epoch(5)轮
for epoch in range(num_epochs):
# 按批次,每次从60000个样本中随机选择100个作为一个批次,共重复600次, enumerate返回坐标100
for i, (images, labels) in enumerate(train_loader):
images = Variable(images.view(-1, 28*28)) # view相当于reshape,将每个image由28*28的矩阵转为1*784, -1代表个数,这里表示100个
labels = Variable(labels)
optimizer.zero_grad() # 梯度清零
outputs = net(images) # 输入网络,进行前向传播
loss = criterion(outputs, labels) # 计算损失值
loss.backward() # 损失后向传播
optimizer.step() # 更新梯度
# 每隔一个批次打印一次结果,也就是每训练100次打印一次结果
if (i+1) % 100 == 0:
print('Epoch [%d/%d], Step [%d/%d], Loss: %.4f'
% (epoch+1, num_epochs, i+1, len(train_dataset)//batch_size, loss.item())
)
- 测试准确率
# test model
correct = 0 # 正确的个数
total = 0 # 预测的总个数(测试集大小)
# 测试集大小为10000,批次大小为100,共100批次
for images, labels in test_loader:
images = Variable(images.view(-1, 28 * 28))
outputs = net(images) # 使用训练好的net
_, predicted = torch.max(outputs.data, 1) # 数字识别共10分类,会得到10个概率值,以最大概率的1类别为预测类别
total += labels.size(0)
correct += (predicted == labels).sum()
# 打印全部测试集上的正确率
print('Accuracy of the network on the 10000 test images: %d %%' % (100*correct//total))
注意在Python3中使用//代替/
结果为:
D:\ProgramData\Anaconda3\envs\torch\python.exe E:/ywj/Thermal_Comfort/DNN_paper1/DNN_example.py
Epoch [1/5], Step [100/600], Loss: 0.4053
Epoch [1/5], Step [200/600], Loss: 0.1726
Epoch [1/5], Step [300/600], Loss: 0.1918
Epoch [1/5], Step [400/600], Loss: 0.1661
Epoch [1/5], Step [500/600], Loss: 0.1460
Epoch [1/5], Step [600/600], Loss: 0.1558
Epoch [2/5], Step [100/600], Loss: 0.1116
Epoch [2/5], Step [200/600], Loss: 0.1017
Epoch [2/5], Step [300/600], Loss: 0.1074
Epoch [2/5], Step [400/600], Loss: 0.0838
Epoch [2/5], Step [500/600], Loss: 0.0902
Epoch [2/5], Step [600/600], Loss: 0.1195
Epoch [3/5], Step [100/600], Loss: 0.0325
Epoch [3/5], Step [200/600], Loss: 0.0621
Epoch [3/5], Step [300/600], Loss: 0.1386
Epoch [3/5], Step [400/600], Loss: 0.1172
Epoch [3/5], Step [500/600], Loss: 0.0993
Epoch [3/5], Step [600/600], Loss: 0.0877
Epoch [4/5], Step [100/600], Loss: 0.0421
Epoch [4/5], Step [200/600], Loss: 0.0173
Epoch [4/5], Step [300/600], Loss: 0.0962
Epoch [4/5], Step [400/600], Loss: 0.1010
Epoch [4/5], Step [500/600], Loss: 0.0445
Epoch [4/5], Step [600/600], Loss: 0.0498
Epoch [5/5], Step [100/600], Loss: 0.0622
Epoch [5/5], Step [200/600], Loss: 0.0096
Epoch [5/5], Step [300/600], Loss: 0.0272
Epoch [5/5], Step [400/600], Loss: 0.0288
Epoch [5/5], Step [500/600], Loss: 0.0324
Epoch [5/5], Step [600/600], Loss: 0.0265
Accuracy of the network on the 10000 test images: 98 %
3. 可视化
让我们画出其Loss变化值,看看效果
可视化工具visdom,使用方法见PyTorch 的可视化工具 Visdom,
当将训练轮数增加为6轮,可以看到准确率开始趋于平稳,准确率依然是98%左右
可视化核心代码:
其中loss_X为训练次数,以100为单位,correct_X为测试批次(以100为单位),loss_arr为每次的loss值,correct_arr为每个批次的准确率。
# 可视化
# 新建名为'demo'的环境
viz = Visdom(env='DNN+MNIST_demo')
viz.line(X=np.array(loss_X), Y=np.array(loss_arr))
viz.line(X=np.array(correct_X), Y=np.array(correct_arr))