使用pytorch进行batch_size分批训练,并使用adam+lbfgs算法——波士顿房价预测

使用pytorch进行batch_size分批训练,并使用adam+lbfgs算法

使用pytorch神经网络进行波士顿房价预测

数据探索

训练过程及结果


python 复制代码
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
import torch
import torch.nn as nn
import torch.optim as optim
from tqdm import tqdm

url = "https://raw.githubusercontent.com/Zhang-bingrui/Boston_house/refs/heads/main/house_data.csv"
boston_df = pd.read_csv(
    url,
    header=0,
    on_bad_lines="skip"   # 跳过格式错误的行,防止报错
)
X = boston_df.drop('MEDV', axis=1).values
y = boston_df['MEDV'].values
#划分训练集和测试集
# Veriyi %20 test setine ve %80 eğitim setine bölelim
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=42)
#输入数据标准化
scaler = StandardScaler()
X_train_scaled = scaler.fit_transform(X_train)
X_test_scaled = scaler.transform(X_test)
#将数据转换为pytorch的TENSOR
X_train = torch.tensor(X_train_scaled,dtype=torch.float32)
X_test = torch.tensor(X_test_scaled,dtype=torch.float32)
y_train = torch.tensor(y_train, dtype=torch.float32).view(-1, 1)
y_test  = torch.tensor(y_test, dtype=torch.float32).view(-1, 1)
#创建数据加载器
train_dataset = TensorDataset(X_train,y_train)
test_dataset = TensorDataset(X_test,y_test)
train_loader = DataLoader(train_dataset,batch_size=64,shuffle=True)
test_loader = DataLoader(test_dataset,batch_size=64,shuffle=False)

# ANN modellerini tanımlayalım
class ANN(nn.Module):
    def __init__(self, input_dim):
        super(ANN, self).__init__()
        self.fc1 = nn.Linear(input_dim, 64)
        self.fc2 = nn.Linear(64, 32)
        self.fc3 = nn.Linear(32, 1)

    def forward(self, x):
        x = torch.relu(self.fc1(x))
        x = torch.relu(self.fc2(x))
        x = self.fc3(x)
        return x


num_epochs = 500
switch_epoch = int(num_epochs * 0.3)

ann_model_batch = ANN(X_train.shape[1])
criterion = nn.MSELoss()

adam_optimizer = optim.Adam(ann_model_batch.parameters(), lr=0.001)
lbfgs_optimizer = optim.LBFGS(
    ann_model_batch.parameters(),
    lr=0.1,
    max_iter=20,
    history_size=100,
    line_search_fn='strong_wolfe'
    )

train_losses_single = []

for epoch in tqdm(range(num_epochs), desc="Training"):

    ann_model_batch.train()

    # ===============================
    # 前 30%:Adam(mini-batch)
    # ===============================
    if epoch < switch_epoch:
        train_loss = 0.0

        for inputs, targets in train_loader:
            adam_optimizer.zero_grad()
            outputs = ann_model_batch(inputs)
            loss = criterion(outputs, targets)
            loss.backward()
            adam_optimizer.step()

            train_loss += loss.item() * inputs.size(0)

        train_loss /= len(train_loader.dataset)

    # ===============================
    # 后 70%:LBFGS(whole-batch)
    # ===============================
    else:
        # 👉 只在第一次进入 LBFGS 时打印
        if epoch == switch_epoch:
            print("\n========== LBFGS 开始训练 ==========\n")

        def closure():
            lbfgs_optimizer.zero_grad()
            outputs = ann_model_batch(X_train)
            loss = criterion(outputs, y_train)
            loss.backward()
            return loss

        loss = lbfgs_optimizer.step(closure)
        train_loss = loss.item()

    train_losses_single.append(train_loss)

    if (epoch + 1) % 50 == 0:
        print(f"Epoch [{epoch+1}/{num_epochs}], Loss: {train_loss:.4f}")


plt.figure(figsize=(8,5))
plt.plot(train_losses_single, label='Adam → LBFGS')
plt.axvline(switch_epoch, color='r', linestyle='--', label='Switch Epoch')
plt.xlabel('Epoch')
plt.ylabel('MSE Loss')
plt.yscale('log')
plt.legend()
plt.show()

整批次训练与分批次训练对比

python 复制代码
url = "https://raw.githubusercontent.com/Zhang-bingrui/Boston_house/refs/heads/main/house_data.csv"

boston_df = pd.read_csv(
    url,
    header=0,
    on_bad_lines="skip"   # 跳过格式错误的行,防止报错
)
# Veri setini özellikler (X) ve hedef değişken (y) olarak ayırın
X = boston_df.drop('MEDV', axis=1).values
y = boston_df['MEDV'].values
#划分训练集和测试集
# Veriyi %20 test setine ve %80 eğitim setine bölelim
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

# Özellikleri ölçeklendirelim
scaler = StandardScaler()
X_train_scaled = scaler.fit_transform(X_train)
X_test_scaled = scaler.transform(X_test)

#将数据转换为pytorch的TENSOR
X_train = torch.tensor(X_train_scaled,dtype=torch.float32)
X_test = torch.tensor(X_test_scaled,dtype=torch.float32)
y_train = torch.tensor(y_train, dtype=torch.float32).view(-1, 1)
y_test  = torch.tensor(y_test, dtype=torch.float32).view(-1, 1)


#创建数据加载器
train_dataset = TensorDataset(X_train,y_train)
test_dataset = TensorDataset(X_test,y_test)




train_loader = DataLoader(train_dataset,batch_size=64,shuffle=True)
test_loader = DataLoader(test_dataset,batch_size=64,shuffle=False)
print(train_loader)
print(test_loader)

# ANN modellerini tanımlayalım
class ANN(nn.Module):
    def __init__(self, input_dim):
        super(ANN, self).__init__()
        self.fc1 = nn.Linear(input_dim, 64)
        self.fc2 = nn.Linear(64, 32)
        self.fc3 = nn.Linear(32, 1)

    def forward(self, x):
        x = torch.relu(self.fc1(x))
        x = torch.relu(self.fc2(x))
        x = self.fc3(x)
        return x

#整批次训练
num_epochs=500
train_losses_whole = []
#初始化模型、损失函数和优化器
ann_model_whole = ANN(X_train.shape[1])
criterion = nn.MSELoss()
optimizer = optim.Adam(ann_model_whole.parameters(), lr=0.001)
inputs = X_train
targets=y_train
for epoch in range(num_epochs):
    ann_model_whole.train()
    optimizer.zero_grad()
    outputs = ann_model_whole(inputs)
    loss = criterion(outputs, targets)
    loss.backward()
    optimizer.step()
    train_losses_whole.append(loss.item())
    if(epoch+1) % 100 == 0:
      print(f'Epoch[{epoch+1}/{num_epochs}]'f'Train Loss:{loss.item():.4f}')

##-----------------------------######------------------------------------#######
# #分批次训练
train_losses_single = []

#初始化模型、损失函数和优化器
ann_model_batch = ANN(X_train.shape[1])
criterion = nn.MSELoss()
optimizer = optim.Adam(ann_model_batch.parameters(), lr=0.001)
for epoch in range(num_epochs):
    #训练模式
    ann_model_batch.train()
    train_loss = 0.0
    for inputs,targets in train_loader:
      optimizer.zero_grad()
      outputs = ann_model_batch(inputs)
      loss = criterion(outputs,targets)
      loss.backward()
      optimizer.step()
      train_loss += loss.item() * inputs.size(0)

    #计算平均训练损失
    train_loss = train_loss / len(train_loader.dataset)
    train_losses_single.append(train_loss)
#    #打印训练进度
    if(epoch+1) % 100 == 0:
      print(f'Epoch[{epoch+1}/{num_epochs}]'f'Train Loss:{train_loss:.4f}')
import matplotlib.pyplot as plt
plt.plot(train_losses_single,label='batch')
plt.plot(train_losses_whole,label='whole')
plt.legend()

绘制结果对比曲线

python 复制代码
# 结果验证
# ===============================
# 预测并绘制对比图
# ===============================
ann_model_batch.eval()

with torch.no_grad():
    y_train_pred = ann_model_batch(X_train).numpy().flatten()
    y_test_pred  = ann_model_batch(X_test).numpy().flatten()

y_train_true = y_train.numpy().flatten()
y_test_true  = y_test.numpy().flatten()

plt.figure(figsize=(6, 6))

# 训练集
plt.scatter(y_train_true, y_train_pred, label='Train')

# 测试集
plt.scatter(y_test_true, y_test_pred, label='Test')

# 理想预测线 y = x
min_val = min(y_train_true.min(), y_test_true.min())
max_val = max(y_train_true.max(), y_test_true.max())
plt.plot([min_val, max_val], [min_val, max_val])

plt.xlabel("True MEDV")
plt.ylabel("Predicted MEDV")
plt.title("Train vs Test Prediction Comparison")
plt.legend()
plt.grid(True)
plt.show()

绘制无序曲线对比结果图

python 复制代码
ann_model_batch.eval()

with torch.no_grad():
    y_train_pred = ann_model_batch(X_train).numpy().flatten()
    y_test_pred  = ann_model_batch(X_test).numpy().flatten()

y_train_true = y_train.numpy().flatten()
y_test_true  = y_test.numpy().flatten()
# 按真实值排序(保证曲线连续)

plt.figure(figsize=(8,4))
plt.plot(y_train_true, label='Train True')
plt.plot(y_train_pred, label='Train Pred')

plt.xlabel("Sample Index (sorted by true value)")
plt.ylabel("MEDV")
plt.title("Training Set: True vs Predicted")
plt.legend()
plt.grid(True)
plt.show()
test_idx = np.argsort(y_test_true)

plt.figure(figsize=(8,4))
plt.plot(y_test_true, label='Test True')
plt.plot(y_test_pred, label='Test Pred')

plt.xlabel("Sample Index (sorted by true value)")
plt.ylabel("MEDV")
plt.title("Test Set: True vs Predicted")
plt.legend()
plt.grid(True)
plt.show()
相关推荐
2401_857683548 分钟前
C++中的原型模式
开发语言·c++·算法
s1hiyu17 分钟前
C++动态链接库开发
开发语言·c++·算法
(❁´◡`❁)Jimmy(❁´◡`❁)18 分钟前
CF2188 C. Restricted Sorting
c语言·开发语言·算法
We་ct18 分钟前
LeetCode 54. 螺旋矩阵:两种解法吃透顺时针遍历逻辑
前端·算法·leetcode·矩阵·typescript
星火开发设计23 分钟前
C++ 预处理指令:#include、#define 与条件编译
java·开发语言·c++·学习·算法·知识
mit6.8241 小时前
dijk|tire+floyd+dp %
算法
独自破碎E1 小时前
【总和拆分 + 双变量遍历】LCR_012_寻找数组的中心下标
数据结构·算法
WBluuue1 小时前
Codeforces 1076 Div3(ABCDEFG)
c++·算法
u0109272711 小时前
模板编译期排序算法
开发语言·c++·算法
GIS瞧葩菜1 小时前
Cesium 轴拖拽 + 旋转圈拖拽 核心数学知识
人工智能·算法·机器学习