pytorch 构建神经网络模型总结

文章目录

        • 1、pytorch的数据类型
        • 2、自动微分功能
        • 3、定义网络模型结构
        • 3.1 定义模型结构
        • 3.2 定义优化器(通过它来改变模型参数)
        • 3.3 定义损失函数(通过它来计算损失,并且计算负反馈的梯度)
        • 4、循环训练神经网络
      • 几个重点理解的地方
        • 5.1 关于RNN的输入
        • 5.2 关于回归的效果影响

1、pytorch的数据类型

pytorch的数据都要使用叫tensor的类型,这个类型的数据应该是为pytorch量身打造的,为后面能够自动微分打下基础,所有的数据类型都应该转化为tensor这个类型

2、自动微分功能

自动微分是为了解决机器学习的反馈问题,非常方便,自动微分要配合损失函数和优化器使用

3、定义网络模型结构

定义需要的网络模型结构,要继承,要定义forward函数

3.1 定义模型结构

3.2 定义优化器(通过它来改变模型参数)

3.3 定义损失函数(通过它来计算损失,并且计算负反馈的梯度)

4、循环训练神经网络

import torch
from  torch import  nn
from torch.autograd import Variable
import numpy as np
import matplotlib.pyplot as plt

#设定种子 保证随机数的产生在程序每次执行时都一样
torch.manual_seed(1)

#---------------- 定义一个RNN 网络模型 --------------------
class My_RNN(nn.Module):
    def __init__(self):
        super(My_RNN,self).__init__()

        # 建立一个基础的RNN网络层
        self.rnn = nn.RNN(
            input_size= 1, # 输入向量的特征维数
            hidden_size=8, # 中间隐藏层节点数
            num_layers= 1,  # 隐藏层数
            nonlinearity= 'relu', # 非线性激活函数
            bias= True,  # 是否有偏置项
            batch_first= True, # 输入数据的格式 (batch_size,step_size,feature_dimension)
            dropout= 0.1, # 随机丢失系数 ,防止过拟合
            bidirectional= False    #
        )
        # 建立输出层
        self.out  = nn.Linear(self.rnn.hidden_size,1)  #输出层把RNN层的32维输出转化为一维输出

    # 前向传递函数,这个函数必须写
    def forward(self,x,state):
        """
        :param x: (batch, time_step, input_size)
        :param state: (n_layers, batch, hidden_size)
        :return: (batch, time_step, output_size)
        """  
        out,state = self.rnn(x,state)  #中间层运算
        out = self.out(out)  #输出层运算

        return out, state

    def train_rnn(self,data_input, data_output, epochs=1, step_size=1, state=None):
        """
        :param data_input: 输入数据一个numpy数组序列
        :param data_output: 输出数据一个numpy数组序列
        :param epochs:  训练数据上跑的遍数
        :param step_size: 时间步长
        :param state: RNN神经网络的中间状态
        :return:
        """
        # ------- 产生一个优化器对象 -------------------
        optimizer = torch.optim.Adam(rnn.parameters(), lr=0.02)

        # ---------产生一个损失函数对象 ------------------
        loss_func = nn.MSELoss()

        for epoch in range(epochs):
            steps = np.int(np.floor(data_input.shape[0] / step_size))
            for step in range(np.int(steps)):
                train_data_in = data_input[step * step_size:(step + 1) * step_size].reshape(1, step_size, 1) #训练数据必须满足(batch_size,Step_size,featur_num)格式
                train_data_in = Variable(torch.from_numpy(train_data_in))  # 包装训练数据
                train_data_out = data_output[step * step_size:(step + 1) * step_size]

                # 前向计算网络输出
                prediction, state = self.forward(train_data_in, state) 
                state = Variable(state.data)                    # 包装state,下一次循环接着用

                # 计算误差,做负反馈
                prediction = prediction.reshape(step_size, )
                train_data_out = torch.from_numpy(train_data_out).reshape(step_size, )
                loss = loss_func(prediction, train_data_out)  # 计算误差
                optimizer.zero_grad()  # clear gradients for this training step
                loss.backward()  # backpropagation, compute gradients
                optimizer.step()  # apply gradients  更新参数

                # -------------绘图--------------------
                if step == 1:  # 每个epoch绘制一次,每个epoch的第一次step绘制
                    plt.plot(np.linspace(0, step_size, step_size, dtype=int), train_data_out.flatten(), 'r-')
                    plt.plot(np.linspace(0, step_size, step_size, dtype=int), prediction.data.numpy().flatten(), 'b-')
                    plt.show()

# -------------------产生训练数据---------------
steps = np.linspace(0*np.pi,50*np.pi,500,dtype=np.float32)
A = np.linspace(2000,0,500,dtype=np.float32)
data_input = np.sin(steps)  * A  + np.cos(2*steps) * (0.5 * A)
data_output = np.cos(steps) * A  + np.sin(5*steps) * (0.5 * A)
#

# #-------------------产生测试数据,从训练数据里面选 --------------------
#
test_steps = np.linspace(0*np.pi,5*np.pi,100,dtype=np.float32)

data_input_test = data_input[100:200].reshape(1,100,1)
data_input_test = torch.from_numpy(data_input_test)

data_output_test = data_output[100:200]


# ------- 产生一个RNN模型的对象 -----------------
rnn = My_RNN()
print(rnn)

#  -------------开始训练 --------------------
rnn.train_rnn(data_input,data_output,20,10)


# -----------利用训练模型产生预测结果------------
state = None                                    #中间隐藏层状态 可以初始化为None
Pre,state = rnn(data_input_test,state)

#把预测结果画出来
plt.plot(test_steps,data_input_test.flatten(),'g') #输入数据
plt.plot(test_steps,data_output_test.flatten(),'r-') #输出真实数据
plt.plot(test_steps,Pre.data.numpy().flatten(),'b-') #输出预测数据
plt.show()

pytorch 构建神经网络模型总结_第1张图片

几个重点理解的地方

5.1 关于RNN的输入

RNN的输入是一个三维的数据,第一维和第二维可以互换,分别表示计算批次大小batch_size或者时间步长step_size,第三维必须是数据的特征维,另外RNN的输入除了这种方式之外,也可以是一种打包好的数据格式,利用pytorch函数

torch.nn.utils.rnn.pack_padded_sequence(input, lengths, batch_first=False, enforce_sorted=True)

这个函数跑一下就就理解了,它是针对输入的step_size大小不一样而作的计算优化

tensor_in = torch.FloatTensor([[1,2,3],[1,0,0]]).resize_(2,3,1)
tensor_in = Variable(tensor_in)
print(tensor_in)
print(tensor_in.shape)

seq_lengths = [3, 3]
pack = nn_utils.rnn.pack_padded_sequence(tensor_in,seq_lengths,batch_first=True)
print(pack)

a = torch.randn((30,1)).reshape(2,5,3)
print(a)

pytorch 构建神经网络模型总结_第2张图片
对于RNN的中间状态输入,初始状态给一个None

5.2 关于回归的效果影响

网络层数影响很大
节点数影响也较大
简单的回归问题,网络层数不要太高,节点数也不要太多

你可能感兴趣的:(python,机器学习)