最近刚入手Pytorch框架,因为论文中需要贴出损失函数的训练过程的曲线,因此就自己写了个函数,通过列表的形式,将训练数据记录下来,并且保存成CSV文件,方便我们以后读取并绘制图像。
一、数据保存成CSV文件
在这里,我们以拟合二次函数为例,首先需要定义一个空的二维列表
定义二维列表:
lossData=[[]]
接着,向里面添加每一步的训练数据,iter代表训练的次数,loss.data.numpy()代表每一次训练的损失值,因为pytorch中,loss是variable类型,因此要使用data,提取其中的数值(tensor类型),再使用numpy,转换成数值类型,方便我们后续绘图使用
将数据保存在二维列表中:
lossData.append([iter,loss.data.numpy()]) #先转成普通tensor,再转成numpy形式
最后,就是自定义一个函数,在训练结束时,将列表数据转换CSV文件
数据转成CSV:
def data_write_csv(file_name, datas): # file_name为写入CSV文件的路径,datas为要写入数据列表
file_csv = codecs.open(file_name, 'w+', 'utf-8') # 追加
writer = csv.writer(file_csv, delimiter=' ', quotechar=' ', quoting=csv.QUOTE_MINIMAL)
for data in datas:
writer.writerow(data)
print("保存文件成功,处理结束")
完整的代码如下:
import torch
from torch.autograd import Variable
import torch.nn.functional as F
import matplotlib.pyplot as plt
import torch.utils.data as Data
torch.manual_seed(1) # reproducible
import csv
import codecs
import numpy as np
def data_write_csv(file_name, datas): # file_name为写入CSV文件的路径,datas为要写入数据列表
file_csv = codecs.open(file_name, 'w+', 'utf-8') # 追加
writer = csv.writer(file_csv, delimiter=' ', quotechar=' ', quoting=csv.QUOTE_MINIMAL)
for data in datas:
writer.writerow(data)
print("保存文件成功,处理结束")
if __name__ == '__main__':
'''快速搭建网络'''
Net = torch.nn.Sequential(
torch.nn.Linear(1, 10),
torch.nn.ReLU(),
torch.nn.Linear(10, 1)
)
'''生成数据'''
#linespace 返回一维的tensor,从step到end,分成Steps个线段得到的向量
#unsqueeze 增加一个维度,tensor要求的数据是二维的
x=torch.unsqueeze(torch.linspace(-1,1,100),dim=1) #shape=(100,1)
#生成标签,前一项是二次函数,后一项是加上随机噪声
#返回一个张量,包含了从区间[0, 1)的均匀分布中抽取的一组随机数
y=x.pow(2)+0.2*torch.rand(x.size())
'''数据批量化'''
BATCH_SIZE=10
EPOCH=20
# 先转换成 torch 能识别的 Dataset
torch_dataset = Data.TensorDataset(x, y)
# 把 dataset 放入 DataLoader
loader = Data.DataLoader(
dataset=torch_dataset, # torch TensorDataset format
batch_size=BATCH_SIZE, # mini batch size
shuffle=True, # (打乱比较好)
num_workers=2, # 多线程来读数据
)
'''训练过程'''
optimizer = torch.optim.SGD(Net.parameters(), lr=0.1) # 传入 net 的所有参数, 学习效率,实例化类,生成对象
loss_func = torch.nn.MSELoss() # 预测值和真实值的误差计算公式 (均方差处理回归),实例化类,生成对象
'''可视化操作'''
lossData=[[]]
iter=0
for epoch in range(EPOCH):
print('Epoch: ', epoch)
for step, (batch_x, batch_y) in enumerate(loader):
b_x = Variable(batch_x) # 务必要用 Variable 包一下,可以在GPU上运算
b_y = Variable(batch_y) #Variable类型的变量会被放到一个计算图中
prediction = Net(b_x) # 喂给 net 训练数据 x, 输出预测值
loss = loss_func(prediction, b_y) # 计算两者的误差
lossData.append([iter,loss.data.numpy()]) #先转成普通tensor,再转成numpy形式
iter+=1
optimizer.zero_grad() # 清空上一步的残余更新参数值
loss.backward() # 误差反向传播, 计算参数更新值
optimizer.step() # 将参数更新值施加到 net 的 p
print("Epoch[{}].step[{}]:loss:{}".format(epoch,step,loss))
if epoch % 10 == 0:
torch.save(Net, ".\\checkpoint\\net_{}.pkl".format(epoch)) # 保存整个网络
data_write_csv(".\\parametres.csv", lossData)
二、读取CSV文件
这里就是自定义一个函数,根据保存的文件形式,按行读取CSV文件的内容,并且使用空格作为分隔符,将每一行的数据分隔成两个,前一个是训练次数,后一个是对应的损失值,特别地,因为首行为空,所以要先将CSV文件的第一行,剔除出来。
这是CSV保存数据的形式:
完整代码:
import torch
from torch.autograd import Variable
import torch.nn.functional as F
import matplotlib.pyplot as plt
import csv
'''读取csv文件'''
def readcsv(files):
csvfile = open(files, 'r')
plots = csv.reader(csvfile, delimiter=' ')#按行读取CSV文件中的数据,每一行以空格作为分隔符,再将内容保存成列表的形式
next( plots) # 读取首行
x = []
y = []
for row in plots:
x.append(float(row[0]))#从csv读取的数据是str类型,转成float类型
y.append(float(row[1]))
return x ,y
plt.figure()
x2,y2=readcsv("parametres.csv")
plt.plot(x2, y2, color='red', linewidth = '1',label='SGD_loss')
plt.xticks(fontsize=20)
plt.yticks(fontsize=20)
plt.ylim(0, 0.2) #y轴取值范围
plt.xlim(0, 200) #x轴取值范围
plt.xlabel('Training Steps',fontsize=15) #x轴标签
plt.ylabel('Training loss',fontsize=15) #y轴标签
plt.legend(fontsize=16) #标签的字号
plt.show()
出图结果: