https://zh.d2l.ai/chapter_recurrent-neural-networks/sequence.html
#%matplotlib inline import torch from torch import nn from d2l import torch as d2l from API_Draw import * T = 1000 # 总共产生1000个点 #time [0,1...,999] time = torch.arange(1, T + 1, dtype=torch.float32) # x = sin(timei*0.01)+高斯噪声 x = torch.sin(0.01 * time) + torch.normal(0, 0.2, (T,)) #画图 #d2l.plot(time, [x], 'time', 'x', xlim=[1, 1000], figsize=(6, 3)) #d2l.plt.show() # 画图 #draw_pic=Animator() #draw_pic.ShowALL_Onec(time,x) # 带噪声的 tau = 4 #T = 1000 # 总共产生1000个点 # 996 - 4 == 0 features = torch.zeros((T - tau, tau)) #features = torch.zeros((2, 3)) # 2行 3列 #print(features) ''' tensor([[0., 0., 0.], [0., 0., 0.]]) ''' for i in range(tau): #print("features:",i,", x:",i,T - tau + i) features[:, i] = x[i: T - tau + i] ''' features: 0列 , x: 0 996 features: 1列 , x: 1 997 features: 2列 , x: 2 998 features: 3列 , x: 3 999 结果 features 有1000(总数)-4(步长)个样本 每个样本有4个连续序列 features 0-3行 0 1 2 3(列) features 0行 x0 x1 x2 x3 features 1行 x1 x2 x3 x4 。。。 features 996行 x996 x997 x998 x999 ''' # labels torch.Size([996, 1]) --> x[4-1000] 拉伸一维度 labels = x[tau:].reshape((-1, 1)) print(labels.shape) #torch.Size([996, 1]) batch_size, n_train = 16, 600 # 仅使用前600个“特征-标签”对进行训练 ''' features[:n_train] 取出前600 作为 features: 0 , x: 0 -600 (996) features: 1 , x: 1 -601 (997) features: 2 , x: 2 -602 (998) features: 3 , x: 3 -603 (999) ''' #n_train=20 print(features[:n_train]) # 取出前 600行(共996行)*4列 作为训练数据 train_iter = d2l.load_array((features[:n_train], labels[:n_train]), batch_size, is_train=True) # 初始化网络权重的函数 def init_weights(m): if type(m) == nn.Linear: nn.init.xavier_uniform_(m.weight) # 一个简单的多层感知机 # #一个拥有两个全连接层的多层感知机,ReLU激活函数和平方损失。 # 样本输入位 4个序列预测一个 输入4 def get_net(): net = nn.Sequential(nn.Linear(4, 10), nn.ReLU(), nn.Linear(10, 1)) net.apply(init_weights) return net # 平方损失。注意:MSELoss计算平方误差时不带系数1/2 loss = nn.MSELoss(reduction='none') def train(net, train_iter, loss, epochs, lr): trainer = torch.optim.Adam(net.parameters(), lr) for epoch in range(epochs): i=0 for X, y in train_iter: #每个批次默认取出8个样本 trainer.zero_grad() l = loss(net(X), y) l.sum().backward() trainer.step() #print("epoch 训练周次",epoch,"样本 train_iter_i",i,"\n样本X \n",X,"\n真值y \n",y,"\n预测Y\n",net(X)) #0-38 ''' 样本X 4*1*N tensor([[-1.0703, -0.9181, -0.8705, -1.2899], [ 0.8708, 0.9502, 1.1182, 1.1485], [ 0.9697, 0.8139, 0.7958, 0.8831], [-0.1353, -0.1559, -0.3127, -0.4170], [ 0.9435, 1.2145, 0.5497, 0.7347], [ 0.8895, 0.9038, 0.9697, 0.8139], [ 0.9038, 0.9697, 0.8139, 0.7958], [-0.6356, -0.6913, -1.0730, -0.6599]]) 真值y 1*1*N tensor([[-1.2054], [ 1.0709], [ 1.2320], [-0.7235], [ 1.0557], [ 0.7958], [ 0.8831], [-1.0967]]) 预测Y 1*1*N tensor([[-0.8696], [ 1.0344], [ 0.8013], [-0.3330], [ 0.8102], [ 0.9025], [ 0.8614], [-0.7655]], grad_fn=<AddmmBackward>) ''' i=i+1 print(f'epoch {epoch + 1}, ' f'loss: {d2l.evaluate_loss(net, train_iter, loss):f}') net = get_net() train(net, train_iter, loss, 5, 0.01) #=========================================== (1) 给我最新的4个数据,预测第5个数据,每次预测值都是真实的最新的 #预测下一个时间步的能力, 也就是单步预测(one-step-ahead prediction)。 #features 0-996 ''' 结果 features 有1000(总数)-4(步长)个样本 每个样本有4个连续序列 features 0-3行 0 1 2 3(列) features 0行 x0 x1 x2 x3 features 1行 x1 x2 x3 x4 ... features 600行 x600 x601 x603 x604 ... features 996行 x996 x997 x998 x999 ''' # 使用原始数据预测 604以后的数据 肯定对 onestep_preds = net(features) # 可视化 d2l.plot([time, time[tau:]], [x.detach().numpy(), onestep_preds.detach().numpy()], 'time', 'x', legend=['data', '1-step preds'], xlim=[1, 1000], figsize=(6, 3)) d2l.plt.show() # # 画图 #draw_pic=Animator() #draw_pic.ShowALL_Onec(time[tau:],onestep_preds.detach().numpy()) # 带噪声的 #=============================== (2) 给定前四个真值,预测出来第五个,然后 真值(2,3,4)+预测值(5)=预测第六个值 后续往复 ,依靠少量近期数据,无限制预测未开数据(天气预报) #我们必须使用我们自己的预测(而不是原始数据)来进行多步预测。 # T=1000 个测试数据 multistep_preds = torch.zeros(T) # n_train =600个 训练数据 # tau = 4 步长 # x[: n_train + tau] x[604 * 4 ] 前604个真实数据 后面 1000-604 都是0 ''' multistep_preds 0-604 真实数据 605-1000 0 ''' multistep_preds[: n_train + tau] = x[: n_train + tau] # 604-1000 使用后续都是0的真实数据来预测 for i in range(n_train + tau, T): multistep_preds[i] = net(multistep_preds[i - tau:i].reshape((1, -1))) #multistep_preds[i - tau:i] # 600-603 真实数据 600 601 602 603 # 601-604 真实数据 601 602 603 预测数据 604 # 。。。 # 997-1000 预测数据 997 998 999 1000 d2l.plot([time, time[tau:], time[n_train + tau:]], [x.detach().numpy(), onestep_preds.detach().numpy(), multistep_preds[n_train + tau:].detach().numpy()], 'time', 'x', legend=['data', '1-step preds', 'multistep preds'], xlim=[1, 1000], figsize=(6, 3)) d2l.plt.show() #经过几个预测步骤之后,预测的结果很快就会衰减到一个常数。 #事实是由于错误的累积 #因此误差可能会相当快地偏离真实的观测结果。 max_steps = 64 #T=1000 #tau=4 # 1000-4-64+1= 933行 , 4+64=68列 [933,68] features = torch.zeros((T - tau - max_steps + 1, tau + max_steps)) # 列i(i<tau)是来自x的观测,其时间步从(i)到(i+T-tau-max_steps+1) # 0-3 for i in range(tau): features[:, i] = x[i: i + T - tau - max_steps + 1] # 0:0+1000-4-64+1= 933 # 1:1+1000-4-64+1= 934 # 2:2+1000-4-64+1= 935 # 3:3+1000-4-64+1= 936 ''' features [i行,前4列数据] 5-68列 x0 x1 x2 x3 0 x1 x2 x3 x4 0 ... x933 x934 x935 x936 0 ''' # 列i(i>=tau)是来自(i-tau+1)步的预测,其时间步从(i)到(i+T-tau-max_steps+1) # 4 - 64+4=68 for i in range(tau, tau + max_steps): features[:, i] = net(features[:, i - tau:i]).reshape(-1) print(i-tau,i,features[:, i - tau:i],features[:, i - tau:i].shape) #933, 4 ''' features[:, i - tau:i] 列操作 列操作 真值 0-3 预测 4 真值 1 2 3 预测值4 预测 5 真值 2 3 预测值4 预测值5 预测 6 真值 3 预测值4 预测值5 预测值6 预测 7 预测值4 预测值5 预测值6 预测值7 预测 8 ... 63-66 预测 67 ''' steps = (1, 4, 16, 64) ''' time 4+1-1=4 : 1000 - 64 + 1=937 [4:937] time 4+4-1=4 : 1000 - 64 + 4=940 [7:940] time 4+16-1=4 : 1000 - 64 + 16=952 [19:952] time 4+64-1=4 : 1000 - 64 + 64=1000 [67:1000] features 4+1-1=4列 933行 真值 0-3 ==》 预测 4 列 features 4+4-1=7列 933行 真值 3 预测值4 预测值5 预测值6 ==》 预测 7列 features 4+16-1=19列 933行 预测值15 预测值16 预测值17 预测值18 ==》预测 19 列 features 4+64-1=67列 933行 预测值63 预测值64 预测值65 预测值66 ==》预测 67 列 ''' d2l.plot([time[tau + i - 1: T - max_steps + i] for i in steps], [features[:, (tau + i - 1)].detach().numpy() for i in steps], 'time', 'x', legend=[f'{i}-step preds' for i in steps], xlim=[5, 1000], figsize=(6, 3)) d2l.plt.show()
API_Draw.py
### 画图 训练损失 训练精度 测试精度 import matplotlib.pyplot as plt import threading import time import matplotlib.animation as animation class Animator: def __init__(self): self.fmts=('-', 'm--', 'g-.', 'r:') #颜色 和线性 #1 基础绘图 #第1步:定义x和y坐标轴上的点 x坐标轴上点的数值 self.x=[] #y坐标轴上点的数值 self.train_loss=[] self.train_acc =[] self.test_acc=[] def add(self, x_,train_loss_,train_acc_,test_acc_ ): self.x.append(x_) self.train_loss.append(train_loss_) self.train_acc.append(train_acc_) self.test_acc.append(test_acc_) # 刷新最新的图像 def ShowALL(self): fig, ax = plt.subplots() plot1=ax.plot(self.x, self.train_loss, self.fmts[0],label="train_loss") plot2=ax.plot(self.x, self.train_acc, self.fmts[1],label="train_acc") plot3=ax.plot(self.x, self.test_acc, self.fmts[2],label="test_acc") plt.legend(bbox_to_anchor=(1, 1),bbox_transform=plt.gcf().transFigure)# 添加图例 plt.grid()#网格 plt.show() # 画单个图 def ShowALL_Onec(self,x,y): fig, ax = plt.subplots() plot1=ax.plot(x, y, self.fmts[0],label="--") #plot2=ax.plot(self.x, self.train_acc, self.fmts[1],label="train_acc") #plot3=ax.plot(self.x, self.test_acc, self.fmts[2],label="test_acc") plt.legend(bbox_to_anchor=(1, 1),bbox_transform=plt.gcf().transFigure)# 添加图例 plt.grid()#网格 plt.show() import threading import time class MyThread(threading.Thread): def __init__(self,name_): threading.Thread.__init__(self) self.name_ = name_ print("线程名字",self.name_ ) self.is_running = 1# 控制标志位 self.animator=Animator() # 画图类 def run(self): while self.is_running: print("Thread is running...") print(self.animator.x,self.animator.train_loss) self.animator.ShowALL() print("线程停止") def stop(self): self.is_running = False # 创建并启动线程 # # 调用 # my_thread = MyThread("可视化训练过程") # my_thread.setDaemon(True)#伴随主进程自动关闭 # my_thread.start() # i=0 # while 1: # i=i+1 # my_thread.animator.add(i,i-3,i-2,i-1) # 加入新数据 # time.sleep(1) # my_thread.stop()# 通过标志为 手动关闭