当前位置: 首页 > article >正文

【深度学习】使用其他深度学习框架(TensorFlow、PyTorch)实现波士顿房价预测任务

深度学习框架

前面学习了使用numpy+python、paddle实现波士顿房价预测任务,为了更加深刻的了解深度学习步骤,决定再选择两种比较流行的其他深度学习框架进行比较。
在这里插入图片描述
我个人听到比较多的是TensorFlow、PyTorch,因此本文章按照前面的波士顿房价预测任务用TensorFlow、PyTorch来实现。

深度学习步骤

1、数据处理
2、模型设计
3、训练配置
4、训练过程
5、模型保存
6、模型推理

1.数据处理

我们暂时认为所有的开源框架对数据处理的代码都是一样的。数据处理包含六个部分:数据获取、数据导入、数据形状变换、数据集划分、数据归一化处理和封装load data函数。数据预处理后,才能被模型调用。
数据获取:百度飞桨提供很多数据集
https://aistudio.baidu.com/datasetoverview

def load_data():
    # 2、数据导入
    # 从文件导入数据
    datafile = './work/housing.data'
    data = np.fromfile(datafile, sep=' ')
    # 3、数据形状变换
    # 每条数据包括14项,其中前面13项是影响因素,第14项是相应的房屋价格中位数
    feature_names = [ 'CRIM', 'ZN', 'INDUS', 'CHAS', 'NOX', 'RM', 'AGE',
                      'DIS', 'RAD', 'TAX', 'PTRATIO', 'B', 'LSTAT', 'MEDV' ]
    feature_num = len(feature_names)
    # 将原始数据进行Reshape,变成[N, 14]这样的形状
    data = data.reshape([data.shape[0] // feature_num, feature_num])
    # 4、数据集划分
    # 将原数据集拆分成训练集和测试集
    # 这里使用80%的数据做训练,20%的数据做测试
    # 测试集和训练集必须是没有交集的
    ratio = 0.8
    offset = int(data.shape[0] * ratio)
    train_data = data[:offset]
    # 5、数据归一化处理
    # 计算训练集的最大值,最小值
    max_values, min_values = train_data.max(axis=0),  train_data.min(axis=0)
    # 对数据进行归一化处理
    for i in range(feature_num):
        data[:, i] = (data[:, i] - min_values[i]) / (max_values[i] - min_values[i])
    # 使用训练集计算最大值和最小值
    # scaler = MinMaxScaler()
    # # 只在训练集上拟合
    # scaler.fit(train_data)
    # data = scaler.transform(data)
    # 训练集和测试集的划分比例
    train_data = data[:offset]
    test_data = data[offset:]
    return train_data, test_data, max_values, min_values

def show_plt(origin, predict, x_index=None):
    if not x_index:
        N = origin.shape[0]  # 数据点的数量
        x_index = np.arange(N)
    # 绘制原始数据 origin
    plt.plot(x_index, origin, color='blue', label='Original Data', alpha=0.6, linewidth=1)
    # 绘制预测数据 predict
    plt.plot(x_index, predict, color='red', label='Predicted Data', linewidth=2)
    # 添加标题和标签(注意:这里我们没有使用实际的 x 值作为横轴标签,因为只有 y 和 predict)
    plt.title('Comparison of Original Data and Predicted Data')
    plt.xlabel('Index')  # 或者你可以使用 'Sample Number'、'Data Point' 等标签
    plt.ylabel('Value')
    plt.legend()
    # 显示图表
    plt.grid(True)
    plt.show()

2.PyTorch

波士顿房价预测任务使用的是线性回归模型,还是按照步骤一步步实现。

2.1.数据处理

2.2.模型设计

# 导入必要的库文件
import torch
import torch.nn as nn
import torch.optim as optim
import numpy as np
# 数据处理中写的两个方法,一个加载数据,一个显示预测结果与原值的曲线图
from load_data import load_data, show_plt
# 定义模型
class Regressor(nn.Module):
    def __init__(self, input_size):
        super(Regressor, self).__init__()
        self.fc = nn.Linear(input_size, 1)

    def forward(self, x):
        x = self.fc(x)
        return x

2.3.训练配置

# 加载数据集
# 使用load_data加载训练集数据和测试集数据
train_data, test_data, max_values, min_values = load_data()
# 初始化模型
model = Regressor(13)
num_epochs = 20  # 设置模型训练轮次
batch_size = 10  # 设置批大小,即一次模型训练使用的样本数量

2.4.训练过程

同样在模型Regressor中定义一个训练方法,训练方法中定义了损失函数和优化器

class Regressor(nn.Module):
    def __init__(self, input_size):
        super(Regressor, self).__init__()
        self.fc = nn.Linear(input_size, 1)

    def forward(self, x):
        x = self.fc(x)
        return x

    def fit_model(self, train_data, num_epochs, batch_size=10):
        # 定义损失函数和优化器
        criterion = nn.MSELoss()
        optimizer = optim.Adam(model.parameters(), lr=0.001)
        # 定义模型训练轮次epoch(外层循环)
        for epoch in range(num_epochs):
            # 对训练集数据进行拆分,batch_size设置为10
            mini_batches = [train_data[k:k + batch_size] for k in range(0, len(train_data), batch_size)]
            # 定义模型训练(内层循环)
            for iter_id, mini_batch in enumerate(mini_batches):
                # 前向传播
                x = np.array(mini_batch[:, :-1])  # 将当前批的房价影响因素的数据转换为np.array格式
                y = np.array(mini_batch[:, -1:])  # 将当前批的标签数据(真实房价)转换为np.array格式
                # 转换为 PyTorch 张量
                x = torch.tensor(x, dtype=torch.float32)
                y = torch.tensor(y, dtype=torch.float32).view(-1, 1)
                outputs = model(x)
                loss = criterion(outputs, y)
                # 反向传播和优化
                optimizer.zero_grad()
                loss.backward()
                optimizer.step()
                if (epoch + 1) % 10 == 0:
                    print(f'Epoch [{epoch + 1}/{num_epochs}], Loss: {loss.item():.4f}')

开始训练

model.fit_model(train_data, num_epochs, batch_size)

2.5 模型保存

# 保存模型
torch.save(model.state_dict(), 'boston_model.pth')
print("模型已保存到 boston_model.pth")

2.6 模型推理

def predict_pytorch():
    # 重新初始化模型
    loaded_model = pytorch_Regressor(13)
    # 加载模型的状态字典
    loaded_model.load_state_dict(torch.load('boston_model.pth'))
    # 设置模型为评估模式
    loaded_model.eval()
    x, y = load_example()
    x = torch.tensor(x, dtype=torch.float32)
    # 使用加载的模型进行预测
    with torch.no_grad():
        predict = loaded_model(x)
    predict = predict * (max_values[-1] - min_values[-1]) + min_values[-1]
    # # 对label数据进行后处理
    y = y * (max_values[-1] - min_values[-1]) + min_values[-1]
    show_plt(y.flatten(), predict.numpy().flatten())

if __name__ == '__main__':
    # predict_paddle()
    predict_pytorch()

在这里插入图片描述

3.TensorFlow

有了pytorch的经验,对于TensorFlow就直接贴完整代码了:
在tensorflow_model.py中,用于训练模型

import os
os.environ['TF_ENABLE_ONEDNN_OPTS'] = '0'
from keras import layers, models
from data import load_data


if __name__ == '__main__':
    # 使用load_data加载训练集数据和测试集数据
    train_data, test_data, max_values, min_values = load_data()
    train_x = train_data[:, :-1]
    train_y = train_data[:, -1]
    # 定义模型
    model = models.Sequential([
        layers.Dense(1, input_shape=(train_x.shape[1],))  # 输出层,无激活函数(回归任务)
    ])
    # 编译模型
    model.compile(optimizer='adam', loss='mse', metrics=['mae'])  # 使用均方误差损失和平均绝对误差指标
    # 训练模型
    history = model.fit(train_x, train_y, epochs=100, batch_size=32, validation_split=0.01, verbose=1)

    # 保存模型
    model.save('tensorflow_model.keras')
    print("模型已保存到 tensorflow_model.keras")

在tensorflow_predict.py中,用于模型推理

import os
os.environ['TF_ENABLE_ONEDNN_OPTS'] = '0'
from keras import layers, models
from data import load_data, show_plt, load_example
train_data, test_data, max_values, min_values = load_data()


def predict():
    # 将模型参数保存到指定路径中
    # 加载模型
    loaded_model = models.load_model('tensorflow_model.keras')
    # 使用加载的模型进行预测
    x, y = load_example()
    predict = loaded_model.predict(x).flatten()
    predict = predict * (max_values[-1] - min_values[-1]) + min_values[-1]
    # # 对label数据进行后处理
    y = y * (max_values[-1] - min_values[-1]) + min_values[-1]
    show_plt(y, predict)


if __name__ == '__main__':
    predict()

在这里插入图片描述

4.python+numpy的完善

前面按照paddle的过程学习了使用 Python 和 NumPy 手动实现模型训练,但是过程中没有保存模型和进行模型推理,这里补充完整。
numpy_model.py

# 导入需要用到的package
import numpy as np
import matplotlib.pyplot as plt
from data import load_data


class Network(object):
    def __init__(self, input_size):
        # 随机产生w的初始值
        # 为了保持程序每次运行结果的一致性,
        # 此处设置固定的随机数种子
        np.random.seed(0)
        self.weights = np.random.randn(input_size, 1)
        self.bias = 0.

    def forward(self, x):
        z = np.dot(x, self.weights) + self.bias
        return z

    def loss(self, z, y):
        error = z - y
        num_samples = error.shape[0]
        cost = error * error
        cost = np.sum(cost) / num_samples
        return cost

    def gradient(self, x, y):
        z = self.forward(x)
        N = x.shape[0]
        gradient_w = 1. / N * np.sum((z - y) * x, axis=0)
        gradient_w = gradient_w[:, np.newaxis]
        gradient_b = 1. / N * np.sum(z - y)
        return gradient_w, gradient_b

    def update(self, gradient_w, gradient_b, eta=0.01):
        self.weights = self.weights - eta * gradient_w
        self.bias = self.bias - eta * gradient_b

    def fit_model(self, train_data, num_epochs, batch_size=10, eta=0.01):
        n = len(train_data)
        losses = []
        for epoch_id in range(num_epochs):
            # 在每轮迭代开始之前,将训练数据的顺序随机打乱
            # 然后再按每次取batch_size条数据的方式取出
            np.random.shuffle(train_data)
            # 将训练数据进行拆分,每个mini_batch包含batch_size条的数据
            mini_batches = [train_data[k:k + batch_size] for k in range(0, n, batch_size)]
            for iter_id, mini_batch in enumerate(mini_batches):
                # print(self.w.shape)
                # print(self.b)
                x = mini_batch[:, :-1]
                y = mini_batch[:, -1:]
                a = self.forward(x)
                loss = self.loss(a, y)
                gradient_w, gradient_b = self.gradient(x, y)
                self.update(gradient_w, gradient_b, eta)
                losses.append(loss)
                print('Epoch {:3d} / iter {:3d}, loss = {:.4f}'.
                      format(epoch_id, iter_id, loss))

        return losses

    def predict(self, x):
        return np.dot(x, self.weights) + self.bias

    def save_model(self, filename):
        np.savez(filename, weights=self.weights, bias=self.bias)
        print(f"模型已保存到 {filename}.npz")


if __name__ == '__main__':
    train_data, test_data, max_values, min_values = load_data()
    # 打乱样本顺序
    np.random.shuffle(train_data)
    # 获取数据
    # 提取前 13 列作为 X
    x = train_data[:, :-1]  # 所有行,列从第 0 列到倒数第 2 列
    # 提取最后一列作为 Y
    y = train_data[:, -1].reshape([len(train_data), 1])   # 所有行,最后一列
    net = Network(13)
    # 启动训练
    losses = net.fit_model(train_data, num_epochs=100, batch_size=20, eta=0.01)
    net.save_model('numpy_model.npz')

numpy_predict.py

# 导入需要用到的package
import numpy as np
from numpy_model import Network as numpy_Regressor
from data import load_data, show_plt, load_example
train_data, test_data, max_values, min_values = load_data()


def predict():
    # 重新初始化模型
    file_name = 'numpy_model.npz'
    data = np.load(file_name)
    loaded_model = numpy_Regressor(input_size=13)
    loaded_model.weights = data['weights']
    loaded_model.bias = data['bias']
    print(f"模型已从 {file_name} 加载")
    x, y = load_example()
    # 使用加载的模型进行预测
    predict = loaded_model.predict(x)
    predict = predict * (max_values[-1] - min_values[-1]) + min_values[-1]
    # # 对label数据进行后处理
    y = y * (max_values[-1] - min_values[-1]) + min_values[-1]
    show_plt(y.flatten(), predict.flatten())


if __name__ == '__main__':
    predict()

4.学习总结

1、matplotlib报错,按照如下方法解决
在这里插入图片描述
2、pytorch、paddle、tensorflow各框架在python依赖库可能会存在版本冲突,最好用conda分开
在这里插入图片描述
3、到目前为止,学习完了用python+numpy、paddle、pytorch、tensorflow四种方式实现波士顿房价预测任务,对于训练的结果都感觉不是很好,也不知道是数据量、模型设计、训练配置哪个环节出的问题。


http://www.kler.cn/a/556526.html

相关文章:

  • Django 5实用指南(五)模板系统
  • python用 PythonNet 从 Python 调用 WPF 类库 UI 用XAML
  • Android JNI的理解与使用。
  • 单片机 code RO-data RW-data ZI-data以及OTA学习
  • DeepSeek本地部署WebUI可视化数据投喂训练AI
  • android13修改系统Launcher不跟随重力感应旋转
  • 深入理解ES6核心特性:现代JavaScript开发的基石
  • 分布式 IO 模块:造纸设备的降本增效利器
  • BERT 大模型
  • LeetCode 2209.用地毯覆盖后的最少白色砖块:记忆化搜索之——深度优先搜索(DFS)
  • 机器学习 - 衡量模型的特性
  • uniapp引入uview组件库(可以引用多个组件)
  • 【机器学习】多元线性回归算法和正规方程解求解
  • 域内证书维权
  • 基于Python+Django+Vue的旅游景区推荐系统系统设计与实现源代码+数据库+使用说明
  • STL —— 洛谷字符串(string库)入门题(蓝桥杯题目训练)(二)
  • 不同安装路径重复R包清理
  • 解耦的艺术_应用架构中的解耦
  • 2024年职高单招或高考计算机类投档线
  • 【AI】openEuler 22.03 LTS SP4安装 docker NVIDIA Container Toolkit