2021-01-31-pytorch实现自定义函数层

Pytorch自定义layer和loss

1、定义函数层(Parameter、forword)

import torch

class MyLayer(torch.nn.Module):
    '''
    因为这个层实现的功能是:y=weights*sqrt(x2+bias),所以有两个参数:
    权值矩阵weights
    偏置矩阵bias
    输入 x 的维度是(in_features,)
    输出 y 的维度是(out_features,) 故而
    bias 的维度是(in_fearures,),注意这里为什么是in_features,而不是out_features,注意体会这里和Linear层的区别所在
    weights 的维度是(in_features, out_features)注意这里为什么是(in_features, out_features),而不是(out_features, in_features),注意体会这里和Linear层的区别所在
    '''
    def __init__(self, in_features, out_features, bias=True):
        super(MyLayer, self).__init__()  # 和自定义模型一样,第一句话就是调用父类的构造函数
        self.in_features = in_features
        self.out_features = out_features
        self.weight = torch.nn.Parameter(torch.Tensor(in_features, out_features)) # 由于weights是可以训练的,所以使用Parameter来定义
        if bias:
            self.bias = torch.nn.Parameter(torch.Tensor(in_features))             # 由于bias是可以训练的,所以使用Parameter来定义
        else:
            self.register_parameter('bias', None)
   def forward(self, input):
        input_=torch.pow(input,2)+self.bias
        y=torch.matmul(input_,self.weight)
        return y
import torch
from my_layer import MyLayer # 自定义层


N, D_in, D_out = 10, 5, 3  # 一共10组样本,输入特征为5,输出特征为3 



class MyNet(torch.nn.Module):
    def __init__(self):
        super(MyNet, self).__init__()  # 第一句话,调用父类的构造函数
        self.mylayer1 = MyLayer(D_in,D_out)
def forward(self, x):
    x = self.mylayer1(x)
 
    return x
model = MyNet()
print(model)
'''运行结果为:
MyNet(
  (mylayer1): MyLayer()   # 这就是自己定义的一个层
)
'''



x = torch.randn(N, D_in)  #(105)
y = torch.randn(N, D_out) #(103)


#定义损失函数
loss_fn = torch.nn.MSELoss(reduction='sum')

learning_rate = 1e-4
#构造一个optimizer对象
optimizer = torch.optim.Adam(model.parameters(), lr=learning_rate)

for t in range(10): # 
 # 第一步:数据的前向传播,计算预测值p_pred
    y_pred = model(x)
     
    # 第二步:计算计算预测值p_pred与真实值的误差
    loss = loss_fn(y_pred, y)
    print(f"第 {t} 个epoch, 损失是 {loss.item()}")
     
    # 在反向传播之前,将模型的梯度归零,这
    optimizer.zero_grad()
     
    # 第三步:反向传播误差
    loss.backward()
     
    # 直接通过梯度一步到位,更新完整个网络的训练参数
    optimizer.step()

2、loss


```c
import torch
import torch.nn as nn
import numpy as np
import matplotlib.pyplot as plt
 
 
# 第一步:自定义损失函数
 
继承nn.Mdule
class My_loss(nn.Module):
    def __init__(self):
        super().__init__()
        
    def forward(self, x, y):
        return torch.mean(torch.pow((x - y), 2))
# 第二步:准备数据集,模拟一个线性拟合过程
x_train = 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]], dtype=np.float32)
 
y_train = 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]], dtype=np.float32)
 
# 将numpy数据转化为torch的张量
inputs = torch.from_numpy(x_train)
targets = torch.from_numpy(y_train)
input_size = 1
output_size = 1
num_epochs = 60
learning_rate = 0.001
 
# 第三步: 构建模型,构建一个一层的网络模型
model = nn.Linear(input_size, output_size)
 
# 与模型相关的配置、损失函数、优化方式
# 使用自定义函数,等价于criterion = nn.MSELoss()
criterion = My_loss()
 
# 定义迭代优化算法, 使用的是随机梯度下降算法
optimizer = torch.optim.SGD(model.parameters(), lr=learning_rate)  
loss_history = []
# 第四步:训练模型,迭代训练
for epoch in range(num_epochs):
    #  前向传播计算网络结构的输出结果
    outputs = model(inputs)
 
    # 计算损失函数
    loss = criterion(outputs, targets)
    
    # 反向传播更新参数,三步策略,归零梯度——>反向传播——>更新参数
    optimizer.zero_grad()
    loss.backward()
    optimizer.step()
 
    # 打印训练信息和保存loss
    loss_history.append(loss.item()) 
    if (epoch+1) % 5 == 0:
        print ('Epoch [{}/{}], Loss: {:.4f}'.format(epoch+1, num_epochs, loss.item()))

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