使用pytorch神经网络拟合计算模型

一. 内容简介

使用pytorch神经网络拟合计算模型

二. 软件环境

2.1vsCode

2.2Anaconda

version: conda 22.9.0

2.3pytorch

安装pytorch(http://t.csdnimg.cn/GVP23)

2.3数据文件

链接:https://pan.baidu.com/s/1csJOoErGyx77MW_FImVKjg?pwd=1234

三.主要流程

3.1 数据集介绍

数据集准备是用matlab多线程计算的,http://t.csdnimg.cn/34MPi
这个数据是前面是参数,后面是结果,用matlab计算的数据,需要拟合这个matlab程序,节省计算时间,里面的数据只是用到了一部分,用这个数据作为训练集,测试没有准备,不太需要,因为计算模型都是算出来的,测试集效果也是挺好的。
在这里插入图片描述

3.2 训练代码

训练代码注释都写在里面了

import numpy as np
import torch
import matplotlib.pyplot as plt
from IPython import display
from d2l import torch as d2l
import random

# prepare datas
# 读取数据集
# 有时候可能会报错,这个文件格式啥的,可以换成自己,设定一下格式,也可以自己创建一下txt,给数据复制进去
data_train = np.loadtxt('./data.txt', delimiter=' ', dtype=np.float64)

# 读取输入参数,也就是模型的输入
x_data = torch.from_numpy(data_train[:, [3,8]])

# 读取模型的输出参数,也就是模型的输出
y_data_1 = torch.from_numpy(data_train[:, [4]]) # [-1] 最后得到的是个矩阵

# 下面是要对数据做一下归一化,如果输入输出量级差的特别多的话,就会出现模型损失很大,没办法很好的拟合模型,可以不归一化训练一下,课程里面有一些可能不会提这个,也可以训练出来,就是数据的量级差的不太多
# 我一直没有归一化,有些模型训练就一直没有训练好
# 计算训练集上的最小值和最大值
x_min, x_max = x_data.min(dim=0)[0], x_data.max(dim=0)[0]
y_min, y_max = y_data_1.min(dim=0)[0], y_data_1.max(dim=0)[0]
# 进行 Min-Max 缩放
x_data_normalized = (x_data - x_min) / (x_max - x_min)
y_data_1_normalized = (y_data_1 - y_min) / (y_max - y_min)

# 覆盖原来的
x_data = x_data_normalized
y_data_1 = y_data_1_normalized

# 这个就是看一下数据集自己换了没
num_rows = len(x_data)
print(num_rows)

# 定义神经网络的结构
# 结构我看着定义的,也可以改
class Model(torch.nn.Module):
    def __init__(self):
        super(Model, self).__init__()
        # 这个是有wx+b
        self.linear1 = torch.nn.Linear(2, 56)
        self.linear2 = torch.nn.Linear(56, 56)
        self.linear3 = torch.nn.Linear(56, 56)
        self.linear4 = torch.nn.Linear(56, 28)
        self.linear5 = torch.nn.Linear(28, 14)
        self.linear6 = torch.nn.Linear(14, 4)
        self.linear7 = torch.nn.Linear(4, 1)
        self.ReLU = torch.nn.ReLU() # 将其看作是网络的一层,而不是简单的函数使用
        self.Sigmoid = torch.nn.Sigmoid()
 
    def forward(self, x):
        x =  self.ReLU(self.linear1(x))
        x =  self.ReLU(self.linear2(x)) 
        x =  self.ReLU(self.linear3(x))
        x =  self.ReLU(self.linear4(x))
        x =  self.ReLU(self.linear5(x))
        x =  self.ReLU(self.linear6(x))
        x =  self.linear7(x)
        return x

# 这个是创建模型
model = Model()

# 下面这个是可以接着之前的模型继续训练,读取之前的模型
# model = torch.torch.load('model1.pkl')
# model = torch.torch.load('averageLoss.pkl')

# 这个给模型设置一下数据的格式,给他设置为64位,精度高一些,为什么设的我也忘了
model = model.to(dtype=torch.float64)

# 这个是给数据集打乱,然后分批拿,按批训练
def data_iter(batch_size, features, labels):
    num_examples = len(features)
    indices = list(range(num_examples))
    # 这块是给数据打乱的
    random.shuffle(indices)
    for i in range(0, num_examples, batch_size):
        batch_indices = torch.tensor(
            indices[i: min(i + batch_size, num_examples)])
        yield features[batch_indices], labels[batch_indices]

# 一批的数据量
# 有时候训练不出来,我一开始给64,32这样的,误差会很大,现在模型训练不出来,我就查数据,和改这个批次的大小
batch_size = 1024

# 这块是设置损失计算的方式,有好几种,个人感觉这种最好
# construct loss and optimizer
# criterion = torch.nn.BCELoss(size_average = True)
criterion = torch.nn.SmoothL1Loss()
# optimizer = torch.optim.Adam(model.parameters(), lr=0.0000001)
# 学习率一般设置较小数:0.01、0.001、0.0001,好的学习率一开始误差就不会特别大的

# 这个是设置学习率,几种动态的调整方式,也是最下面那个最好,以前好像比过
# 定义Adam优化器
adam_optimizer = torch.optim.Adam(model.parameters(), lr=0.001)
# 定义Adagrad优化器
adagrad_optimizer = torch.optim.Adagrad(model.parameters(), lr=0.001)
# 定义RMSprop优化器
rmsprop_optimizer = torch.optim.RMSprop(model.parameters(), lr=0.001)

optimizer = torch.optim.Adam(model.parameters(), lr=0.0001)

# 这是之前设置的动态学习率,就是训练不下去以后,给学习率降低,设置一个耐心值,没耐心了就降学习率,至于为什么耐心给这么大,因为降了以后训练模型不太好,
# 这个就是知道就行了,不怎么用
# 动态学习率
lr_scheduler = torch.optim.lr_scheduler.ReduceLROnPlateau(optimizer, mode='min', factor=0.1000000000000000, patience=200000000000000000000000, cooldown=5, eps=1e-30)
# lr_scheduler.step(loss)

# 迭代次数
num_epochs = 160000000000000000000

# 单批最小损失,一轮迭代损失
# 用来保存损失最小的模型
lossMin = 10000000
lossAverage = 10000000

# training cycle forward, backward, update
# 下面就是训练,更新模型参数
for epoch in range(num_epochs):
    # 取一批数据
    for x, y in data_iter(batch_size, x_data, y_data_1):
        # 计算数据预测结果
        y_pred = model(x)
        # 计算损失
        loss = criterion(y_pred,y)
        # 清除梯度
        optimizer.zero_grad()
        # 反向传播
        loss.backward()
        # 更新参数
        optimizer.step()
        # 只是一个批次的最优,
        if loss < lossMin:
            lossMin = loss
            # torch.save(model,'minLoss.pkl')
    with torch.no_grad():
        # 计算损失
        train_l = criterion(model(x_data), y_data_1)
        # 更新学习率
        # 计算平均参数
        lr_scheduler.step(train_l.mean())
        # 读取学习率数值
        lr = optimizer.param_groups[0]['lr']

        # 保存损失最低的模型
        if train_l < lossAverage:
            lossAverage = train_l
            # 这个是存模型 
            torch.save(model,'angelminLoss.pkl')
            # 有最优的模型,在打印批次
            print('epoch {}, averageLoss {}, lr {}, averageLoss {}, minLoss {}'.format(epoch + 1, float(train_l.mean()), float(lr), float(lossAverage), float(lossMin)))

在这里插入图片描述

3.3 查看模型训练效果

训练效果代码,输出的误差有点不太对,就看差值就行了

import numpy as np
import matplotlib.pyplot as plt
from IPython import display
from d2l import torch as d2l
import random
import numpy as np
import torch
import matplotlib.pyplot as plt
from IPython import display
from d2l import torch as d2

# 网络的结构在写一下,
class Model(torch.nn.Module):
    def __init__(self):
        super(Model, self).__init__()
        # 这个是有wx+b
        self.linear1 = torch.nn.Linear(2, 56)
        self.linear2 = torch.nn.Linear(56, 56)
        self.linear3 = torch.nn.Linear(56, 56)
        self.linear4 = torch.nn.Linear(56, 28)
        self.linear5 = torch.nn.Linear(28, 14)
        self.linear6 = torch.nn.Linear(14, 4)
        self.linear7 = torch.nn.Linear(4, 1)
        self.ReLU = torch.nn.ReLU() # 将其看作是网络的一层,而不是简单的函数使用
        self.Sigmoid = torch.nn.Sigmoid()
 
    def forward(self, x):
        x =  self.ReLU(self.linear1(x))
        x =  self.ReLU(self.linear2(x)) 
        x =  self.ReLU(self.linear3(x))
        x =  self.ReLU(self.linear4(x))
        x =  self.ReLU(self.linear5(x))
        x =  self.ReLU(self.linear6(x))
        x =  self.linear7(x)
        return x

# 读取训练好的模型,这个angelminLoss.pkl是不包含结构的,只是参数,所以上面要写网络的结构
model = torch.torch.load('angelminLoss.pkl')

# 读取数据集
data_train = np.loadtxt('./data.txt', delimiter=' ', dtype=np.float64)

# 读取输入参数
x_data = torch.from_numpy(data_train[:100000, [3,8]])
# 读取输出参数
y_data_1 = torch.from_numpy(data_train[:100000, [4]]) # [-1] 最后得到的是个矩阵

# 还是归一,因为模型输出的是一个归一化的结果,所以需要给他变成原来的
# 计算训练集上的最小值和最大值
x_min, x_max = x_data.min(dim=0)[0], x_data.max(dim=0)[0]
y_min, y_max = y_data_1.min(dim=0)[0], y_data_1.max(dim=0)[0]
# 进行 Min-Max 缩放
x_data_normalized = (x_data - x_min) / (x_max - x_min)
y_data_1_normalized = (y_data_1 - y_min) / (y_max - y_min)
x_data = x_data_normalized
y_data_1 = y_data_1_normalized

# 存损失啥的,以及个数
num_rows, num_cols = x_data.shape
sum  = 0
result = np.zeros(num_rows)

# 计数用
countRes = 0
for a in range(num_rows):
    y = model(x_data[a])*(y_max - y_min) + y_min
    sum = sum + abs((y_data_1[a]*(y_max - y_min) + y_min - y).item())
    result[a] = abs((y_data_1[a]*(y_max - y_min) + y_min - y).item())
    if result[a] > 0.001:
        print("实际值: {} ;预测值: {} ;差值: {} ;误差: {} ;".format((y_data_1[a]*(y_max - y_min) + y_min).item(),y.item(),((y_data_1[a]*(y_max - y_min) + y_min) - y).item(),((((y_data_1[a]*(y_max - y_min) + y_min) - y)/(y_data_1[a]*(y_max - y_min) + y_min))*100).item()))
        print(" {} {};".format(x_data[a][0].item(),x_data[a][1].item()))
        countRes = countRes + 1 
print(countRes)
average = sum / num_rows

print("平均误差: {} ; 最大误差: {} ; 最小误差: {} ;".format(average, max(abs(result)), min(abs(result))))

在这里插入图片描述

四.参考

代码是这个老师讲的基础上改的,加了一下东西,原型是这个,老师讲的很好
【《PyTorch深度学习实践》完结合集】 https://www.bilibili.com/video/BV1Y7411d7Ys/?share_source=copy_web&vd_source=7b377d4a833a67013df5f95f32b390f8

李沐老师讲的也特别好,要更深一些,六二大人老师讲的基础一些
【00 预告【动手学深度学习v2】】 https://www.bilibili.com/video/BV1if4y147hS/?share_source=copy_web&vd_source=7b377d4a833a67013df5f95f32b390f8

李宏毅老师神经网络的原理讲的特别好,这个我没有找到官方的号,可以自己哔哩哔哩搜

  • 10
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值