3-7 使用深度学习解决温度即示数问题

3-7 使用深度学习解决温度即示数问题

直接上代码

%matplotlib inline
import matplotlib.pyplot as plt
import numpy as np
import torch
torch.set_printoptions(edgeitems=2, linewidth=75)

设置Jupyter Notebook在单元格中内嵌显示图像,导入所需库并设置PyTorch的打印选项。

#%%
t_c = [0.5,  14.0, 15.0, 28.0, 11.0,  8.0,  3.0, -4.0,  6.0, 13.0, 21.0]
t_u = [35.7, 55.9, 58.2, 81.9, 56.3, 48.9, 33.9, 21.8, 48.4, 60.4, 68.4]
t_c = torch.tensor(t_c)
t_u = torch.tensor(t_u)

定义摄氏温度和未知温度的样本数据,并将它们转换为PyTorch张量。

#%%
def model(t_u, w, b):
    return w * t_u + b

定义线性模型:$ t_p = w \times t_u + b $。

#%%
def loss_fn(t_p, t_c):
    squared_diffs = (t_p - t_c) ** 2
    return squared_diffs.mean()

定义损失函数,使用均方误差(MSE)来计算预测值和真实值之间的差异。

#%%
def dloss_fn(t_p, t_c):
    dsq_diffs = 2 * (t_p - t_c) / t_p.size(0)
    return dsq_diffs

def dmodel_dw(t_u, w, b):
    return t_u

def dmodel_db(t_u, w, b):
    return 1.0

定义损失函数对预测值的梯度,以及模型对参数(w和b)的梯度。

#%%
def grad_fn(t_u, t_c, t_p, w, b):
    dloss_dtp = dloss_fn(t_p, t_c)
    dloss_dw = dloss_dtp * dmodel_dw(t_u, w, b)
    dloss_db = dloss_dtp * dmodel_db(t_u, w, b)
    return torch.stack([dloss_dw.sum(), dloss_db.sum()])

计算损失函数对参数w和b的梯度。

#%%
w = torch.zeros(())
b = torch.zeros(())

初始化参数w和b为0。

#%%
delta = 0.1
loss_rate_of_change_w = (loss_fn(model(t_u, w + delta, b), t_c) - loss_fn(model(t_u, w - delta, b), t_c)) / (2.0 * delta)
learning_rate = 1e-2
w = w - learning_rate * loss_rate_of_change_w

loss_rate_of_change_b = (loss_fn(model(t_u, w, b + delta), t_c) - loss_fn(model(t_u, w, b - delta), t_c)) / (2.0 * delta)
b  = b - learning_rate * loss_rate_of_change_b

计算参数w和b的梯度并进行一次梯度下降更新。

#%%
def training_loop(n_epochs, learning_rate, params, t_u, t_c):
    for epoch in range(1, n_epochs+1):
        w, b = params
        t_p = model(t_u, w, b)
        loss = loss_fn(t_p, t_c)
        grad = grad_fn(t_u, t_c, t_p, w, b)
        params = params - learning_rate * grad
        print("Epoch %d, Loss %f" % (epoch, float(loss)))
    return params

定义训练循环函数,通过多个训练周期更新参数。

#%%
training_loop(
    n_epochs = 100,
    learning_rate = 1e-5,
    params = torch.tensor([1.0, 0.0]),
    t_u = t_u,
    t_c = t_c)

调用训练循环函数,执行100个训练周期。

#%%
t_un = 0.1 * t_u
params = training_loop(
    n_epochs = 3000,
    learning_rate = 1e-2,
    params = torch.tensor([1.0, 0.0]),
    t_u = t_un,
    t_c = t_c
)

对输入数据进行缩放并再次训练模型,这次训练3000个周期。

#%%
t_p = model(t_un, *params)
fig = plt.figure(dpi=600)
plt.xlabel("Temperature Fahrenheit")
plt.ylabel("Temperature Celsius")
plt.plot(t_u.numpy(), t_p.detach().numpy())
plt.plot(t_u.numpy(), t_c.numpy(), 'o')
plt.savefig("temp_unknown_plot.png", format='png')

绘制模型预测值与真实值的对比图。

#%%
params = torch.tensor([1.0, 0.0], requires_grad=True)

初始化参数并设置requires_grad=True以允许梯度计算。

#%%
loss = loss_fn(model(t_u, *params), t_c)
loss.backward()
params.grad

计算损失并反向传播以获取梯度。

#%%
def training_loop(n_epochs, learning_rate, params, t_u, t_c): 
    for epoch in range(1, n_epochs + 1): 
        if params.grad is not None: 
            params.grad.zero_() 
        t_p = model(t_u, *params) 
        loss = loss_fn(t_p, t_c)
        loss.backward() 
        with torch.no_grad(): 
            params -= learning_rate * params.grad
        if epoch % 500 == 0: 
            print('Epoch %d, Loss %f' % (epoch, float(loss))) 
    return params

更新训练循环以在每个周期中清零梯度,并在没有梯度计算的上下文中更新参数。

#%%
params = training_loop(
    n_epochs = 3000,
    learning_rate = 1e-2,
    params = params,
    t_u = t_un,
    t_c = t_c
)

使用新的训练循环进行训练。

#%%
import torch.optim as optim
params = torch.tensor([1.0, 0.0], requires_grad=True)
learning_rate = 1e-5
optimizer = optim.SGD([params], lr=learning_rate)

t_p = model(t_u, *params)
loss = loss_fn(t_p, t_c)
loss.backward()

optimizer.step()
params

使用PyTorch的优化器(SGD)进行参数更新。

#%%
def training_loop(n_epochs, optimizer, params, t_u, t_c):
    for epoch in range(1, n_epochs + 1):
        t_p = model(t_u, *params)
        loss = loss_fn(t_p,t_c)
        optimizer.zero_grad()
        loss.backward()
        optimizer.step()
        if epoch % 500 == 0:
            print("Epoch %d, Loss %f" % (epoch, float(loss)))
    return params

更新训练循环以使用优化器进行参数更新。

#%%
params = torch.tensor([1.0, 0.0], requires_grad=True)
learning_rate = 1e-2
optimizer = optim.SGD([params], lr=learning_rate)

training_loop(
    n_epochs = 5000,
    optimizer = optimizer,
    params = params,
    t_u = t_un,
    t_c = t_c
)

调用更新后的训练循环。

#%%
t_c = torch.tensor(t_c).unsqueeze(1)
t_u = torch.tensor(t_u).unsqueeze(1)

调整数据的形状,使其成为二维张量。

#%%
t_u.shape

检查数据的形状。

#%%
n_samples = t_u.shape[0]
n_val = int(0.2 * n_samples)

shuffled_indices = torch.randperm(n_samples)

train_indices = shuffled_indices[:-n_val]
val_indices = shuffled_indices[-n_val:]

t_u_train = t_u[train_indices]
t_c_train = t_c[train_indices]

t_u_val = t_u[val_indices]
t_c_val = t_c[val_indices]

t_un_train = 0.1 * t_u_train
t_un_val = 0.1 * t_u_val

将数据划分为训练集和验证集,并对训练数据进行缩放。

#%%
import torch.nn as nn

linear_model = nn.Linear(1,1)
linear_model(t_un_val)

定义一个线性模型并进行前向传播。

#%%
x = torch.ones(10,1)
linear_model(x)

测试线性模型的前向传播。

#%%
optimizer = optim.SGD(linear_model.parameters(), lr=1e-2)
list(linear_model.parameters())

定义优化器并查看模型参数。

#%%
def train_loop(n_epochs, optimizer, model, loss_fn,

 t_u_train, t_u_val, t_c_train, t_c_val):
    for epoch in range(1, n_epochs + 1):
        t_p_train = model(t_u_train)
        loss_train = loss_fn(t_p_train, t_c_train)
        
        t_p_val = model(t_u_val)
        loss_val = loss_fn(t_p_val, t_c_val)
        
        optimizer.zero_grad()
        loss_train.backward()
        optimizer.step()
        
        if epoch == 1 or epoch % 1000 == 0:
            print(f"Epoch {epoch}, Training loss {loss_train.item():.4f},"
                f"Validation loss {loss_val.item():.4f}")

定义训练循环函数,包括训练和验证集的损失计算和模型更新。

#%%
def loss_fn(t_p, t_c):
    squared_diffs = (t_p - t_c)**2
    return squared_diffs.mean()

linear_model = nn.Linear(1,1)
optimizer = optim.SGD(linear_model.parameters(), lr=1e-2)

train_loop(
    n_epochs = 3000,
    optimizer = optimizer,
    model = linear_model,
    loss_fn = loss_fn,
    t_u_train = t_un_train,
    t_u_val = t_un_val,
    t_c_train = t_c_train,
    t_c_val = t_c_val)

定义损失函数并调用训练循环函数。

#%%
seq_model = nn.Sequential(
            nn.Linear(1,13),
            nn.Tanh(),
            nn.Linear(13,1))
seq_model

定义一个顺序模型,包含一个隐藏层和一个输出层。

#%%
from collections import OrderedDict

seq_model = nn.Sequential(OrderedDict([
    ('hidden_linear', nn.Linear(1, 8)),
    ('hidden_activation', nn.Tanh()),
    ('output_linear', nn.Linear(8,1))
]))

seq_model

使用OrderedDict重新定义顺序模型。

#%%
optimizer = optim.SGD(seq_model.parameters(), lr = 1e-4)
train_loop(
        n_epochs = 10000,
        optimizer = optimizer,
        model = seq_model,
        loss_fn = nn.MSELoss(),
        t_u_train = t_un_train,
        t_u_val = t_un_val,
        t_c_train = t_c_train,
        t_c_val = t_c_val
)

使用新的顺序模型 seq_model 和均方误差损失函数(MSELoss),初始化优化器并运行训练循环,训练 10000 个周期。

#%%
print("output", seq_model(t_un_val))
print("answer", t_c_val)
print("hidden", seq_model.hidden_linear.weight.grad)

打印顺序模型在验证集上的预测输出和真实值,查看隐藏层线性变换的权重梯度。

#%%
import matplotlib.pyplot as plt

t_range = torch.arange(20.,90.).unsqueeze(1)

fig = plt.figure(dpi=600)
plt.xlabel("Fahrenheit")
plt.ylabel("Celsius")
plt.plot(t_u.numpy(), t_c.numpy(), 'o')
plt.plot(t_range.numpy(), seq_model(0.1 * t_range).detach().numpy(), 'c-')
plt.plot(t_u.numpy(), seq_model(0.1 * t_u).detach().numpy(), 'kx')
plt.show()

绘制图形来显示模型预测值与真实值的对比。
在这里插入图片描述
在这里插入图片描述

图中有三个部分:

  1. 圆点表示原始数据点。
  2. 青蓝色的线表示顺序模型在指定范围内的预测。
  3. 叉号表示模型在训练数据上的预测。

这个代码通过训练简单的线性模型和顺序模型(包含隐藏层)来预测摄氏温度。并展示了如何使用PyTorch的自动微分功能和优化器来更新模型参数。

相关推荐

  1. 7-3 求完

    2024-07-10 08:24:01       42 阅读

最近更新

  1. easyExcel

    easyExcel

    2024-07-10 08:24:01      0 阅读
  2. 什么是等保测评

    2024-07-10 08:24:01       0 阅读
  3. acml可用订阅到起始位姿

    2024-07-10 08:24:01       0 阅读
  4. Windows 12 网页版

    2024-07-10 08:24:01       0 阅读
  5. 网络融合的艺术:Xcode中应用Web服务集成全指南

    2024-07-10 08:24:01       0 阅读
  6. 提示工程的技术与策略分类

    2024-07-10 08:24:01       0 阅读
  7. css font 优化

    2024-07-10 08:24:01       0 阅读
  8. 基于深度学习的金融交易

    2024-07-10 08:24:01       0 阅读
  9. MATLAB中balance函数用法

    2024-07-10 08:24:01       0 阅读
  10. 栈和队列之间有哪些区别

    2024-07-10 08:24:01       0 阅读
  11. python 爬虫技术 第04节 函数和模块

    2024-07-10 08:24:01       0 阅读

热门阅读

  1. Transformer和Bert的原理是什么

    2024-07-10 08:24:01       5 阅读
  2. 使用tkinter 制作工作流ui

    2024-07-10 08:24:01       7 阅读
  3. postman工具介绍

    2024-07-10 08:24:01       8 阅读
  4. vue-路由自动化

    2024-07-10 08:24:01       5 阅读
  5. el-date-picker 扩展

    2024-07-10 08:24:01       8 阅读
  6. Go语言入门之变量、常量、指针以及数据类型

    2024-07-10 08:24:01       4 阅读
  7. Kotlin 处理livedata数据倒灌

    2024-07-10 08:24:01       6 阅读
  8. 针对vue3的render函数添加自定义指令

    2024-07-10 08:24:01       8 阅读
  9. Kotlin中的关键字

    2024-07-10 08:24:01       6 阅读
  10. Matlab 使用

    2024-07-10 08:24:01       9 阅读
  11. AI学习指南机器学习篇-层次聚类原理

    2024-07-10 08:24:01       8 阅读
  12. k8s-第一节-minikube

    2024-07-10 08:24:01       6 阅读
  13. 基于gunicorn+flask+docker模型高并发部署

    2024-07-10 08:24:01       7 阅读