用户定制化torch.autograd.Function以及使用tensorboard可视化分析

代码展示:

import matplotlib.pyplot as plt
import numpy as np 
import torch
from torch import nn
from torch.autograd import Function
from torch.autograd import gradcheck
import random
import os
from torch.utils.tensorboard import SummaryWriter
# from tensorboardX import SummaryWriter
writer = SummaryWriter()
seed = 20200910
os.environ['PYTHONHASHSEED'] = str(seed)
torch.manual_seed(seed)
torch.cuda.manual_seed(seed)
torch.cuda.manual_seed_all(seed)  # if you are using multi-GPU.
np.random.seed(seed)  # Numpy module.
random.seed(seed)  # Python random module.
torch.manual_seed(seed)
torch.backends.cudnn.benchmark = False
torch.backends.cudnn.deterministic = True


class LinearFunction4cxq(Function):
    @staticmethod
    def forward(ctx, input, weight, bias=None):
        # ctx.save_for_backward只能保存张量tensor,不能保存其他类型否则报错
        # TypeError: save_for_backward can only save variables, but argument 3 is of type str
        # 如果希望保存其他数据类型可以使用这种方式: ctx.constant = constant
        # 然后再backward()方法中取回这个数据,使用这种方式: ctx.constant
        ctx.save_for_backward(input, weight, bias)  # (20, 20) (30, 20) (30,)
        output = input.mm(weight.t())  # (20, 30)
        if bias is not None:
            output += bias.unsqueeze(0).expand_as(output)  # (20, 30) 
        return output  # (20, 30)
    @staticmethod
    def backward(ctx, grad_output):  # (20, 30)
        input, weight, bias = ctx.saved_tensors  # (20, 20) (30, 20) (30,)
        grad_input = grad_weight = grad_bias = None
        if ctx.needs_input_grad[0]:
            grad_input = grad_output.mm(weight)  # (20, 20)
        if ctx.needs_input_grad[1]:
            grad_weight = grad_output.t().mm(input)  # (30, 20)
        if bias is not None and ctx.needs_input_grad[2]:
            grad_bias = grad_output.sum(0)  # (30,)
            # grad_bias = grad_output.sum(0).squeeze(0)
        return grad_input, grad_weight, grad_bias  # (20, 20) # (30, 20) # (30,)

linear4ccxxqq = LinearFunction4cxq.apply
class LinearModule4cxq(nn.Module):
    def __init__(self, input_features, output_features, bias=True):
        super(LinearModule4cxq, self).__init__()
        self.input_features = input_features
        self.output_features = output_features
        self.weight = nn.Parameter(torch.Tensor(output_features, input_features))
        if bias:
            self.bias = nn.Parameter(torch.Tensor(output_features))
        else:
            self.register_parameter('bias', None)  # 这行代码会将self.bias设置成None
        self.weight.data.uniform_(-0.1, 0.1)
        # print('林麻子self.bias',self.bias,'#########')
        # print('林麻子bias',bias,'#########')
        if bias:
            self.bias.data.uniform_(-0.1, 0.1)
    def forward(self, input):
        # return LinearFunction4cxq.apply(input, self.weight, self.bias)
        return linear4ccxxqq(input, self.weight, self.bias)  # 这两行语句效果相同
    def extra_repr(self):
        '''该方法用于打印信息'''
        return 'in_features={}, out_features={}, bias={}'.format(
            self.input_features, self.output_features, self.bias is not None
        )

if __name__ == "__main__":
    # pass
    linear4cxq = LinearFunction4cxq.apply
    input_cxq = (
        torch.randn(20,20,dtype=torch.double,requires_grad=True), 
        torch.randn(30,20,dtype=torch.double,requires_grad=True),
        # torch.randn(30,dtype=torch.double,requires_grad=True)  # bias可用可不用,建议这行代码用上,用以检查bias的自动梯度
    )
    test = gradcheck(linear4cxq, input_cxq, eps=1e-6, atol=1e-4)
    print('\n测试是否通过:',test)
    print('\n')
    print('开始创建LinearModule4cxq'.center(80,'-'))
    model = LinearModule4cxq(input_features=1, output_features=1, bias=True)  # True # False
    print(model)
    model.cuda()
    optimizer = torch.optim.Adam(model.parameters(), lr=0.001)
    # 模拟华氏度与摄氏度之间的转换  
    # Fahrenheit = 32 + 1.8 * Celsius
    model.train()
    cost = torch.nn.MSELoss()


    # 将图结构添加到tensorboard中,来进行可视化
    Celsius = torch.randn(1,1,dtype=torch.float).cuda()
    writer.add_graph(model, input_to_model=Celsius, verbose=False)


    epochs = 100001  # 100001
    print('\n')
    print('开始训练LinearModule4cxq'.center(80,'-'))
    list4delta = list()
    list4epoch = list()
    for epoch in range(epochs):
        with torch.no_grad():
            Celsius = torch.randn(1,1,dtype=torch.float).cuda()
            Fahrenheit = 32.0 + 1.8 * Celsius
            Fahrenheit = Fahrenheit.cuda()

        # Celsius = torch.randn(1,1,dtype=torch.float,requires_grad=False).cuda()  # requires_grad=False  True
        # Fahrenheit = 32.0 + 1.8 * Celsius
        # Fahrenheit = Fahrenheit.cuda()        # requires_grad=False

        output = model(Celsius)
        loss = cost(output, Fahrenheit)
        if epoch % 1000 == 0:  # if epoch % 1000 == 0:
            writer.add_scalar('Loss/train', loss, epoch)
            list4delta += [(output - Fahrenheit).detach().item()]
            list4epoch += [epoch]

        optimizer.zero_grad()
        loss.backward()
        optimizer.step()
        if epoch % 5000 == 0:
            info = '\nepoch:{0:>6}/{1:<6}\t'.format(epoch,epochs)
            for k, v in model.state_dict().items():
                info += str(k)+ ':' + str(v.item()) + '\t'
            print(info)

fig, ax = plt.subplots() 
# ax.plot(10*np.random.randn(100),10*np.random.randn(100),'o')
ax.plot(list4epoch, list4delta, 'r.-', markersize=8)
ax.set_title("Visualization For My Model's Errors")
# plt.show()
writer.add_figure(
    'matplotlib figure', 
    fig, 
    global_step=None, 
    close=False, 
    walltime=None)


writer.flush()
writer.close()
# tensorboard --logdir=runs

控制台输出结果:

Windows PowerShell
版权所有 (C) Microsoft Corporation。保留所有权利。

尝试新的跨平台 PowerShell https://aka.ms/pscore6

加载个人及系统配置文件用了 779 毫秒。
(base) PS C:\Users\chenxuqi\Desktop\News4cxq\test4cxq> conda activate pytorch_1.7.1_cu102
(pytorch_1.7.1_cu102) PS C:\Users\chenxuqi\Desktop\News4cxq\test4cxq>  & 'D:\Anaconda3\envs\pytorch_1.7.1_cu102\python.exe' 'c:\Users\chenxuqi\.vscode\extensions\ms-python.python-2020.12.424452561\pythonFiles\lib\python\debugpy\launcher' '50056' '--' 'c:\Users\chenxuqi\Desktop\News4cxq\test4cxq\test11.py'

测试是否通过: True


------------------------------开始创建LinearModule4cxq------------------------------
LinearModule4cxq(in_features=1, out_features=1, bias=True)


------------------------------开始训练LinearModule4cxq------------------------------

epoch:     0/100001     weight:-0.046415962278842926    bias:0.0799543485045433

epoch:  5000/100001     weight:0.29525384306907654      bias:4.958519458770752

epoch: 10000/100001     weight:0.5240390300750732       bias:9.761096954345703

epoch: 15000/100001     weight:0.7794860005378723       bias:14.521628379821777

epoch: 20000/100001     weight:0.8959959149360657       bias:19.208402633666992

epoch: 25000/100001     weight:1.2659095525741577       bias:23.782440185546875

epoch: 30000/100001     weight:1.5608582496643066       bias:28.086692810058594

epoch: 35000/100001     weight:1.7663363218307495       bias:31.460214614868164

epoch: 40000/100001     weight:1.7999906539916992       bias:31.999900817871094

epoch: 45000/100001     weight:1.7999987602233887       bias:31.999996185302734

epoch: 50000/100001     weight:1.7999999523162842       bias:32.0

epoch: 55000/100001     weight:1.7999999523162842       bias:32.0

epoch: 65000/100001     weight:1.7999999523162842       bias:32.0

epoch: 70000/100001     weight:1.7999999523162842       bias:32.0

epoch: 75000/100001     weight:1.7999999523162842       bias:32.0

epoch: 80000/100001     weight:1.7999999523162842       bias:32.0

epoch: 85000/100001     weight:1.7999999523162842       bias:32.0

epoch: 90000/100001     weight:1.7999999523162842       bias:32.0

epoch: 95000/100001     weight:1.7999999523162842       bias:32.0

epoch:100000/100001     weight:1.7999999523162842       bias:32.0
(pytorch_1.7.1_cu102) PS C:\Users\chenxuqi\Desktop\News4cxq\test4cxq> 
(pytorch_1.7.1_cu102) PS C:\Users\chenxuqi\Desktop\News4cxq\test4cxq> tensorboard --logdir=runs
TensorFlow installation not found - running with reduced feature set.
Serving TensorBoard on localhost; to expose to the network, use a proxy or pass --bind_all
TensorBoard 2.4.0 at http://localhost:6006/ (Press CTRL+C to quit)

tensorboard显示效果截图:
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

代码展示:

import matplotlib.pyplot as plt
import numpy as np 
import torch
from torch import nn
from torch.autograd import Function
import random
import os
seed = 20200910
os.environ['PYTHONHASHSEED'] = str(seed)
torch.manual_seed(seed)
torch.cuda.manual_seed(seed)
torch.cuda.manual_seed_all(seed)  # if you are using multi-GPU.
np.random.seed(seed)  # Numpy module.
random.seed(seed)  # Python random module.
torch.manual_seed(seed)
torch.backends.cudnn.benchmark = False
torch.backends.cudnn.deterministic = True


class LinearFunction4cxq(Function):
    @staticmethod
    def forward(ctx, input, weight, bias=None):
        # ctx.save_for_backward只能保存张量tensor,不能保存其他类型否则报错
        # TypeError: save_for_backward can only save variables, but argument 3 is of type str
        # 如果希望保存其他数据类型可以使用这种方式: ctx.constant = constant
        # 然后再backward()方法中取回这个数据,使用这种方式: ctx.constant
        ctx.save_for_backward(input, weight, bias)  # (20, 20) (30, 20) (30,)
        output = input.mm(weight.t())  # (20, 30)
        if bias is not None:
            output += bias.unsqueeze(0).expand_as(output)  # (20, 30) 
        return output  # (20, 30)
    @staticmethod
    def backward(ctx, grad_output):  # (20, 30)
        input, weight, bias = ctx.saved_tensors  # (20, 20) (30, 20) (30,)
        grad_input = grad_weight = grad_bias = None
        if ctx.needs_input_grad[0]:
            grad_input = grad_output.mm(weight)  # (20, 20)
        if ctx.needs_input_grad[1]:
            grad_weight = grad_output.t().mm(input)  # (30, 20)
        if bias is not None and ctx.needs_input_grad[2]:
            grad_bias = grad_output.sum(0)  # (30,)
            # grad_bias = grad_output.sum(0).squeeze(0)
        return grad_input, grad_weight, grad_bias  # (20, 20) # (30, 20) # (30,)

linear4ccxxqq = LinearFunction4cxq.apply
class LinearModule4cxq(nn.Module):
    def __init__(self, input_features, output_features, bias=True):
        super(LinearModule4cxq, self).__init__()
        self.input_features = input_features
        self.output_features = output_features
        self.weight = nn.Parameter(torch.Tensor(output_features, input_features))
        if bias:
            self.bias = nn.Parameter(torch.Tensor(output_features))
        else:
            self.register_parameter('bias', None)  # 这行代码会将self.bias设置成None
        self.weight.data.uniform_(-0.1, 0.1)
        # print('林麻子self.bias',self.bias,'#########')
        # print('林麻子bias',bias,'#########')
        if bias:
            self.bias.data.uniform_(-0.1, 0.1)
    def forward(self, input):
        # return LinearFunction4cxq.apply(input, self.weight, self.bias)
        return linear4ccxxqq(input, self.weight, self.bias)  # 这两行语句效果相同
    def extra_repr(self):
        '''该方法用于打印信息'''
        return 'in_features={}, out_features={}, bias={}'.format(
            self.input_features, self.output_features, self.bias is not None
        )

if __name__ == "__main__":
    print('开始创建LinearModule4cxq'.center(80,'-'))
    model = LinearModule4cxq(input_features=1, output_features=1, bias=True)  # True # False
    model.cuda()
    optimizer = torch.optim.Adam(model.parameters(), lr=0.001)
    # 模拟华氏度与摄氏度之间的转换  
    # Fahrenheit = 32 + 1.8 * Celsius
    model.train()
    cost = torch.nn.MSELoss()

    Celsius = torch.randn(1,1,dtype=torch.float).cuda()

    epochs = 100001  # 100001
    print('\n')
    print('开始训练LinearModule4cxq'.center(80,'-'))
    list4delta = list()
    list4epoch = list()
    for epoch in range(epochs):
        with torch.no_grad():
            Celsius = torch.randn(10,1,dtype=torch.float).cuda()
            Fahrenheit = 32.0 + 1.8 * Celsius
            Fahrenheit = Fahrenheit.cuda()

        # Celsius = torch.randn(1,1,dtype=torch.float,requires_grad=False).cuda()  # requires_grad=False  True
        # Fahrenheit = 32.0 + 1.8 * Celsius
        # Fahrenheit = Fahrenheit.cuda()        # requires_grad=False

        output = model(Celsius)
        loss = cost(output, Fahrenheit)
        if epoch % 1000 == 0:  # if epoch % 1000 == 0:
            list4delta.append(torch.pow((output - Fahrenheit).detach(),2).sum().item())
            list4epoch.append(epoch)

        optimizer.zero_grad()
        loss.backward()
        optimizer.step()
        if epoch % 5000 == 0:
            info = '\nepoch:{0:>6}/{1:<6}\t'.format(epoch,epochs)
            for k, v in model.state_dict().items():
                info += str(k)+ ':' + str(v.item()) + '\t'
            print(info)

fig, ax = plt.subplots() 
# ax.plot(10*np.random.randn(100),10*np.random.randn(100),'o')
ax.plot(list4epoch, list4delta, 'r.-', markersize=8)
ax.set_title("Visualization For My Model's Errors")
plt.show()


控制台输出结果:

Windows PowerShell
版权所有 (C) Microsoft Corporation。保留所有权利。

尝试新的跨平台 PowerShell https://aka.ms/pscore6

加载个人及系统配置文件用了 856 毫秒。
(base) PS C:\Users\chenxuqi\Desktop\News4cxq\测试学习率调度器> conda activate pytorch_1.7.1_cu102
(pytorch_1.7.1_cu102) PS C:\Users\chenxuqi\Desktop\News4cxq\测试学习率调度器>  & 'D:\Anaconda3\envs\pytorch_1.7.1_cu102\python.exe' 'c:\Users\chenxuqi\.vscode\extensions\ms-python.python-2021.1.502429796\pythonFiles\lib\python\debugpy\launcher' '64829' '--' 'c:\Users\chenxuqi\Desktop\News4cxq\测试学习率调度器\test02.py'       
------------------------------开始创建LinearModule4cxq------------------------------


------------------------------开始训练LinearModule4cxq------------------------------

epoch:     0/100001     weight:0.09733616560697556      bias:0.09860190004110336        

epoch:  5000/100001     weight:0.7290825247764587       bias:4.986055850982666  

epoch: 10000/100001     weight:1.1657215356826782       bias:9.796563148498535  

epoch: 15000/100001     weight:1.4271074533462524       bias:14.562826156616211 

epoch: 20000/100001     weight:1.6228671073913574       bias:19.261140823364258 

epoch: 25000/100001     weight:1.715320348739624        bias:23.83855438232422

epoch: 30000/100001     weight:1.768678903579712        bias:28.146183013916016

epoch: 35000/100001     weight:1.8001339435577393       bias:31.49368667602539

epoch: 40000/100001     weight:1.7999986410140991       bias:31.999900817871094

epoch: 45000/100001     weight:1.800002098083496        bias:31.99999237060547

epoch: 50000/100001     weight:1.7999999523162842       bias:32.0

epoch: 55000/100001     weight:1.7999999523162842       bias:32.0

epoch: 60000/100001     weight:1.7999999523162842       bias:32.0

epoch: 65000/100001     weight:1.7999999523162842       bias:32.0

epoch: 70000/100001     weight:1.7999999523162842       bias:32.0

epoch: 75000/100001     weight:1.7999999523162842       bias:32.0

epoch: 80000/100001     weight:1.7999999523162842       bias:32.0

epoch: 85000/100001     weight:1.7999999523162842       bias:32.0

epoch: 90000/100001     weight:1.7999999523162842       bias:32.0

epoch: 95000/100001     weight:1.7999999523162842       bias:32.0

epoch:100000/100001     weight:1.7999999523162842       bias:32.0

运行结果展示:

在这里插入图片描述
在这里插入图片描述

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值