致谢:赵越人工智能AI开发课(Python+PyCharm+PyTorch)。
人人都能听懂的课,参见原视频课赵越人工智能AI开发课(Python+PyCharm+PyTorch)-学习视频教程-腾讯课堂
# coding=utf-8
import torch
from torch import optim
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from torch import nn
# 解决中文乱码方法
from pylab import mpl
'''
---解决OMP: Error #15: Initializing libiomp5md.dll, but found libiomp5md.dll already initialized. OMP: Hi
'''
import os
os.environ['KMP_DUPLICATE_LIB_OK'] = 'TRUE'
#---end
mpl.rcParams['font.sans-serif'] = ['KaiTi'] # 指定默认字体FangSong仿宋
mpl.rcParams['axes.unicode_minus'] = False # 解决保存图像是负号'-'显示为方块的问题
#标准化
def normalize(data):
mu = torch.mean(data)
std = torch.std(data)
return (data - mu)/std
#归一化
def guiyimaxmin(x):
min = torch.min(x)
max = torch.max(x)
return (x - min) / (max - min)
npx=np.random.randint(0,100,(1000,1))
npy=np.power(npx,4)/3+npx*8+80
#实现矩阵拼接
npxy=np.concatenate((npx,npy),axis=1)
#Dataframe是一种数据框结构,相当于是一个矩阵形式,单元格可以存放数值、字符串等,这和excel表很像;
pdx=pd.Dataframe(npxy,columns=['x','y'])
#生成1data.xlsx
pdx.to_excel('1data.xlsx',sheet_name='Sheet1',header=True,index=False)
#sheetname='Sheet1'表示第一张sheet
# header=True,把列标也就是‘x’显示出来
# index=False,不需要添加行标
#读取1data.xlsx
pdxy = pd.read_excel('1data.xlsx')
#sheetname=0表示第一张sheet
# header=0,第一行作为各列名
# index_col=0 去掉添加的列标
#转为张量数据
data = torch.tensor(pdxy.values,dtype=torch.float)
#训练数据行
train_rows=900
#预测数据行
test_rows=100
x=data[0:train_rows,0:-1]
x=guiyimaxmin(x)
y=data[0:train_rows,[-1]]
x1 = data[train_rows:train_rows+test_rows, 0:-1]
x1=guiyimaxmin(x1)
y1 = data[train_rows:train_rows+test_rows, [-1]]
class Net(torch.nn.Module):
def __init__(self):
super(Net, self).__init__()
self.conv1 = nn.Sequential(
#线性层(下同)
nn.Linear(1,20),
#激活函数(下同)
nn.ReLU(),
nn.Linear(20,10),
nn.ReLU(),
nn.Linear(10, 5),
nn.ReLU(),
nn.Linear(5,1)
)
#前向传播
def forward(self, x):
x = self.conv1(x)
return x
#指定设备类型,可以是CPU,也可以是GPU
# device=torch.device('cpu')
device = torch.device('cuda:0' if torch.cuda.is_available() else 'cpu')
#前向传播求出预测的值
model = Net().to(device)
#损失函数
criteon = nn.MSELoss().to(device)
#优化器
optimizer = optim.Adam(model.parameters(), lr=0.3)
trainlosslist=[]
testlosslist=[]
plt.ion()
#训练次数,采用梯度下降法
for epoch in range(401):
model.train()
x, y = x.to(device), y.to(device)
logits = model(x)
#求loss
loss = criteon(logits, y)
#梯度置零,也就是把loss关于权重的导数变成0
optimizer.zero_grad()
#反向传播求梯度
loss.backward()
#更新所有参数
optimizer.step()
# print(epoch, 'loss:', loss.item()) # loss.item()将一个零维张量转换成浮点数
trainlosslist.append(loss.item())
model.eval()
#不需要计算梯度,也不会进行反向传播
with torch.no_grad(): # test
x1, y1 = x1.to(device), y1.to(device)
logits = model(x1)
testloss = criteon(logits, y1)
testlosslist.append(testloss.item())
#'''
if epoch % 20 == 0:
plt.cla()
l3=plt.scatter(np.arange(y1.shape[0]),y1.to(device='cpu'))
l4=plt.scatter(np.arange(logits.shape[0]),logits.to(device='cpu'))
plt.legend([l3, l4], ['%d个值的真实结果'% y1.shape[0], '%d个值的预测结果'% y1.shape[0]], loc='upper right')
plt.text(0.5, 0, '训练次数=%d' % epoch, fontdict={'size': 20, 'color': 'red'})
plt.pause(0.2)
#'''
'''
在交互模式下:
1、plt.plot(x)或plt.imshow(x)是直接出图像,不需要plt.show()
2、如果在脚本中使用ion()命令开启了交互模式,没有使用ioff()关闭的话,则图像会一闪而过,并不会常留。要想防止这种情况,需要在plt.show()之前加上ioff()命令。
在阻塞模式下:
1、打开一个窗口以后必须关掉才能打开下一个新的窗口。这种情况下,默认是不能像Matlab一样同时开很多窗口进行对比的。
2、plt.plot(x)或plt.imshow(x)是直接出图像,需要plt.show()后才能显示图像
'''
plt.ioff()
#l1 = plt.plot(trainlosslist)
#l2 = plt.plot(testlosslist)
#plt.legend([l1,l2],['tranloss','testloss'],loc='best')
#plt.xlabel('epochs')
plt.show()