Pytorch-learn2-构建简单的神经网络

在Pytorch-learn1中,我已经介绍了pytorch的简单操作,接下来让我们来构建简单的神经网络。

首先还是库的导入。这次我们除了torch和numpy,还需要导入可视化库来观察模型的预测结果,和数据处理计算库。

#-------库的导入------
import torch
import torch.nn as nn
import numpy as np
import torch.optim as optim#优化器
#数据处理与计算
from sklearn.metrics import mean_squared_error
from sklearn.preprocessing import MinMaxScaler
#数据可视化
import matplotlib.pyplot as plt
#阻止一些无意义的警告
import warnings
warnings.filterwarnings('ignore')

导入成功库之后,我们需要对数据进行训练集和测试集的划分。在这里我们用自定义的数据划分库。

def split_dataset(datax,datay,shuffle,testsize):#划分训练集和测试集
    if shuffle:#时序模型一般不shuffle
        random_num = [i for i in range(len(datax))]
        np.random.shuffle(random_num)
        datax = datax[random_num]
        datay = datay[random_num]
    split_num = int(len(datax)*testsize)
    train_x = datax[:split_num,:]
    train_y = datay[:split_num,:]
    testx = datax[split_num:,:]
    testy = datay[split_num:,:]
    return train_x, train_y, testx, testy

之后就是我们的数据集,其中x1和x2作为feature(输入特征),y_data作为label(参照)

# -------测试数据集--------
x1 = np.array([[3.3], [4.4], [5.5], [6.71], [6.93], [4.168],[9.779], [6.182], [7.59],
                    [2.167], [7.042], [10.791], [5.313], [7.997], [3.1],[3.75],[3.25]], dtype=np.float32)
x2 = np.array([[3.1], [4.1], [5.53], [6.712], [6.937], [4.1682],[9.4], [6.18], [7.77],
                    [2.11], [6.88], [11.65], [5.22], [7.57], [3.35],[3.79],[3.225]], dtype=np.float32)
y_data = np.array([[1.7], [2.76], [2.09], [3.19], [1.694], [1.573], [3.366], [2.596], [2.53],
                    [1.221], [2.827], [3.465], [1.65], [2.904], [1.3],[1.59],[1.56]], dtype=np.float32)

有了数据集,就要对数据进行合并于归一化处理。

x_data=np.stack([x1,x2],axis=1).squeeze()
##-----------归一化处理-----------
# 创建 MinMaxScaler 对象
x_scaler,y_scaler = MinMaxScaler(),MinMaxScaler()
x_data = x_scaler.fit_transform(x_data)
y_data=y_scaler.fit_transform(y_data)#可以用scaler.inverse_transform(y_data)反归一化
#-------划分训练集和测试集,要求输入x的第一维为特征数量--------
train_x, train_y, testx,testy = split_dataset(x_data,y_data,False,0.7)

接下来我们要运用多个激活函数构造神经网络哦,每个神经元都包含了一个激活函数。理论上来讲,只要激活函数的数量够多够复杂,这个函数集能模拟任意一种函数曲线。Pytorch为我们提供了各种激活函数,他们的基本图像如下。

接下来就是构建我们的神经网络。这里为了展示一下神经网络的堆叠使用了三层隐藏层。

#----------构建简单的神经网络---------
class Simple_Linear(nn.Module):
    def __init__(self):
        super(Simple_Linear, self).__init__()#获取输入
        # Simple_Linear.__init__(self)  # 用父类名称继承父类的init方法
        self.fc1 = nn.Linear(2, 16)  # 输入层到第一个隐藏层
        self.fc2 = nn.Linear(16, 32)  # 第一个隐藏层到第二个隐藏层
        self.fc3 = nn.Linear(32, 16)  # 第二个隐藏层到第三个隐藏层
        self.fc4 = nn.Linear(16, 1)   # 第三个隐藏层到输出层
        # 记录隐藏层的数量及其架构
        self.hidden_layers = [
            ('fc1', self.fc1),
            ('fc2', self.fc2),
            ('fc3', self.fc3),
        ]
    def forward(self,x):#前向传播层
        x=torch.relu(self.fc1(x))
        x = torch.sigmoid(self.fc2(x))
        x = torch.relu(self.fc3(x))
        x=self.fc4(x)
        return x
    def print_hidden_layers(self):#模型内置结构
        print("隐藏层数量:", len(self.hidden_layers))
        print("隐藏层架构:")
        for name, layer in self.hidden_layers:
            print(f"{name}: Input size = {layer.in_features}, Output size = {layer.out_features}")
    def __str__(self):
        return f'{self.hidden_layers}'

接下来,如果电脑有GPU,就将模型转到GPU上训练

#-------转到GPU上训练---------
device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
print(f"Device: {torch.cuda.get_device_name()}")
model=Simple_Linear().to(device)
print(model.print_hidden_layers())#查看模型内置参数

然后,我们对Hyperparameters(超参数)进行设置。这里使用了广泛使用的Adam优化器,相较于传统的梯度下降法,它是RMSProp和Momentum的集合方法,表现更优。

#-------定义超参数-------
learning_rate=0.5e-2#学习率
num_epochs=200#训练次数
# 定义损失函数和优化器
criterion = nn.MSELoss()  # 均方误差损失函数用于回归
#beta1的值越小对小梯度变化越敏感
optimizer=optim.Adam(model.parameters(),lr=learning_rate,betas=(0.5, 0.999))

接下来就是训练模型了。

#-----------训练模型------------
for epoch in range(num_epochs):
    inputs=torch.from_numpy(train_x).to(device)#输入
    labels=torch.from_numpy(train_y).to(device)#参照
    # 前向传播
    outputs=model(inputs)
    loss=criterion(outputs,labels)
    model.train()#不加会影响到如 Dropout 和 BatchNorm
    # 后向传播与优化
    optimizer.zero_grad()#归零梯度,如果不归零,梯度值会不断累加
    loss.backward()#进行反向传播,计算损失函数 loss 对模型参数的梯度
    #前一步计算得到的梯度以及预定义的学习率,调整模型参数以最小化损失函数
    optimizer.step()
    if (epoch + 1) % 10 == 0:
        model.eval()
        with torch.no_grad():
            test_x=torch.from_numpy(testx).to(device)
            test_y = torch.from_numpy(testy).to(device)
            output = model(test_x)
            test_loss = criterion(output, test_y)
        print('Epoch [{}/{}], Loss: {:.3f}'.format(epoch + 1, num_epochs, test_loss.item()))

对于训练好的模型,我们用测试集验证他的性能。记住,对前面归一化后的数据我们要进行反归一化。

#-----获得预测结果-----
xx_test = torch.from_numpy(testx).float().to(device)
pred = model(xx_test)
predicted=pred.cpu().detach().numpy()
#------反归一化------
predicted=y_scaler.inverse_transform(predicted)
testy=y_scaler.inverse_transform(testy)
#计算RMSE和R
rmse = np.sqrt(mean_squared_error(predicted, testy))
pearson_corr = np.corrcoef(np.array(predicted).squeeze(), np.array(testy).squeeze())[0, 1]

最后可视化我们模型在测试集上的表现结果

#--------可视化--------
plt.plot(testy, 'ro', label='Original data')
plt.plot(predicted, label='Fitted line')
plt.text(0.80, 0.85 ,f'Corr: {pearson_corr:.2f}', transform=plt.gca().transAxes, fontsize=10,c='k',
         verticalalignment='top')
plt.text(0.80, 0.79 ,f'RMSE: {rmse:.2f}', transform=plt.gca().transAxes, fontsize=10,c='k',
         verticalalignment='top')
plt.legend()
plt.show()

以上是构建神经网络的全过程,在数据量少的情况下,通常不建议使用过于复杂的神经网络,在数据具有时间序列等周期特征或数据量庞大时,可能要考虑更为复杂的模型。 

  • 8
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值