每一行-样本,每一列-特征

对于mini batch: σ[]=[σ]

    

          N*1                         N*8                                        8*1                    N*1

向量化过程:将输入合成一个矩阵

隐藏层越多-->学习能力越强,但不代表学习能力越强越好,需要泛化能力

因此需要进行超参数搜索的方式找到最优参数

对一个多输入单输出的回归任务,构建模型求解如下

import sklearn
from sklearn.model_selection import train_test_split
import torch
import torch.nn as nn
import numpy as np
import matplotlib.pyplot as plt

# 加载数据
x = np.loadtxt('rawdata/diabetes_data.csv', delimiter=' ', dtype=np.float32)
y = np.loadtxt('target/y.csv', delimiter=',', dtype=np.float32)

# 将数据转换为Tensor
x_data = torch.from_numpy(x)
y_data = torch.from_numpy(y.astype(np.float32)).view(-1, 1)

# 划分训练集和测试集(80%训练集,20%测试集)
x_train, x_test, y_train, y_test = train_test_split(x_data, y_data, test_size=0.2, random_state=42)

# 打印训练集和测试集的形状
print("x_train shape:", x_train.shape)
print("y_train shape:", y_train.shape)
print("x_test shape:", x_test.shape)
print("y_test shape:", y_test.shape)

# 定义模型
class Model(nn.Module):
    def __init__(self):
        super(Model, self).__init__()
        self.linear1 = nn.Linear(10, 16)
        self.linear2 = nn.Linear(16, 8)
        self.linear3 = nn.Linear(8,4)
        self.linear4=nn.Linear(4,1)
        self.relu = nn.ReLU()

    def forward(self, x):
        x = self.relu(self.linear1(x))
        x = self.relu(self.linear2(x))
        x = self.relu(self.linear3(x))
        x = self.linear4(x)
        return x

# 初始化模型、损失函数和优化器
model = Model()
criterion = nn.MSELoss(reduction='mean')  # 使用'none'时可以返回每个样本的损失
optimizer = torch.optim.Adam(model.parameters(), lr=0.001)

# 训练过程
"""使用训练集统计量对特征与标签进行标准化,有助于稳定与加速收敛"""
x_mean = x_train.mean(dim=0)
x_std = x_train.std(dim=0) + 1e-8
y_mean = y_train.mean()
y_std = y_train.std() + 1e-8

x_train = (x_train - x_mean) / x_std
x_test = (x_test - x_mean) / x_std
y_train = (y_train - y_mean) / y_std
y_test = (y_test - y_mean) / y_std

for epoch in range(1000):
    model.train()  # 确保在训练模式下
    y_pred = model(x_train)
    loss = criterion(y_pred, y_train)
    print(epoch, loss.item())

    optimizer.zero_grad()
    loss.backward()
    optimizer.step()

    # 每10个epoch计算一次测试集的损失
    if epoch % 50 == 0:
        model.eval()  # 进入评估模式
        with torch.no_grad():
            y_test_pred = model(x_test)
            test_loss = criterion(y_test_pred, y_test)
            # 额外输出反标准化后的RMSE,便于直观理解
            y_test_pred_raw = y_test_pred * y_std + y_mean
            y_test_raw = y_test * y_std + y_mean
            raw_mse = criterion(y_test_pred_raw, y_test_raw).item()
            print(f"Epoch {epoch} - Test Loss(z): {test_loss.item():.6f} | Test RMSE(raw): {raw_mse ** 0.5:.3f}")

# 训练结束后在测试集上做可视化(预测值 vs 真实值)
model.eval()
with torch.no_grad():
    y_test_pred = model(x_test)
    y_test_pred_raw = (y_test_pred * y_std + y_mean).squeeze().cpu().numpy()
    y_test_raw = (y_test * y_std + y_mean).squeeze().cpu().numpy()

# 绘制 parity plot(y_true vs y_pred)
plt.figure(figsize=(6, 6))
plt.scatter(y_test_raw, y_test_pred_raw, alpha=0.6, edgecolors='none')

# 画 y = x 的参考线
min_val = min(float(np.min(y_test_raw)), float(np.min(y_test_pred_raw)))
max_val = max(float(np.max(y_test_raw)), float(np.max(y_test_pred_raw)))
plt.plot([min_val, max_val], [min_val, max_val], 'r--', linewidth=1)

# 计算并显示RMSE
rmse = float(np.sqrt(np.mean((y_test_pred_raw - y_test_raw) ** 2)))
plt.title(f"Test Predictions vs True (RMSE={rmse:.2f})")
plt.xlabel("True")
plt.ylabel("Predicted")
plt.xlim(min_val, max_val)
plt.ylim(min_val, max_val)
plt.gca().set_aspect('equal', adjustable='box')
plt.tight_layout()
plt.savefig('test_pred_vs_true.png', dpi=150)
plt.show()

若使用min batch,training cycle要写作嵌套循环

外层循环为epoch,内层循环对batch进行循环,每一次操作一个mini batch

for epoch in range(training_epochs):#对所有样本进行了一次前馈和反馈
    for i in range(total_batch):#一次训练的样本数量
#iteration 为有几个mini batch
#eg. 10000examples,batch size=1000,iteration=10

加载数据集操作:需支持索引,即使用下标操作

同时Dataloader可以进行shuffle操作

下面是使用dataloader完成的

import torch
import torch.nn as nn
from torch.utils.data import Dataset#抽象类,无法实例化
from torch.utils.data import DataLoader
import numpy as np
class DiabetesDataset(Dataset):
    def __init__(self,filepath):
        x = np.loadtxt('rawdata/diabetes_data.csv', delimiter=' ', dtype=np.float32)
        y = np.loadtxt('target/y.csv', delimiter=',', dtype=np.float32)
        self.len=x.shape[0]
        self.x_data = torch.from_numpy(x)
        self.y_data = torch.from_numpy(y.astype(np.float32)).view(-1, 1)
        pass
    #1. 所有data加载到内存里,在getitem时把第i个传出去-->小数据集
    #2. 非结构化数据,文件名放列表里
    def __getitem__(self, index):
        return self.x_data[index],self.y_data[index]
    def __len__(self):
        return self.len

dataset=DiabetesDataset()
train_loader=DataLoader(dataset=dataset,batch_size=32,shuffle=True,num_workers=2)#读取数据集过程是否并行
class Model(nn.Module):
    def __init__(self):
        super(Model, self).__init__()
        self.linear1 = nn.Linear(10, 16)
        self.linear2 = nn.Linear(16, 8)
        self.linear3 = nn.Linear(8,4)
        self.linear4=nn.Linear(4,1)
        self.relu = nn.ReLU()

    def forward(self, x):
        x = self.relu(self.linear1(x))
        x = self.relu(self.linear2(x))
        x = self.relu(self.linear3(x))
        x = self.linear4(x)
        return x

# 初始化模型、损失函数和优化器
model = Model()
criterion = nn.MSELoss(reduction='mean')  # 使用'none'时可以返回每个样本的损失
optimizer = torch.optim.Adam(model.parameters(), lr=0.001)

for epoch in range(100):
    for i,data in enumerate(train_loader,0):
        inputs,labels=data#自动转化为tensor

        y_pred=model(inputs)
        loss=criterion(y_pred,labels)
        print(epoch,i,loss.item())

        optimizer.zero_grad()
        loss.backward()

        optimizer.step()

更多推荐