学深度学习ep05--多维特征输入
·
每一行-样本,每一列-特征

对于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()
更多推荐
所有评论(0)