Python打卡训练营day32
DAY 33 简单的神经网络
知识点回顾:
PyTorch和cuda的安装
查看显卡信息的命令行命令(cmd中使用)
cuda的检查
简单神经网络的流程
数据预处理(归一化、转换成张量)
模型的定义
继承nn.Module类
定义每一个层
定义前向传播流程
定义损失函数和优化器
定义训练流程
可视化loss过程
预处理补充:
注意事项:
1. 分类任务中,若标签是整数(如 0/1/2 类别),需转为long类型(对应 PyTorch 的torch.long),否则交叉熵损失函数会报错。
2. 回归任务中,标签需转为float类型(如torch.float32)。
作业:今日的代码,要做到能够手敲。这已经是最简单最基础的版本了。
import torch
print(torch.__version__) # 输出版本号
print(torch.cuda.is_available()) # 检查 GPU 支持(True 表示可用)# 仍然用4特征,3分类的鸢尾花数据集作为我们今天的数据集
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
import numpy as np# 加载鸢尾花数据集
iris = load_iris()
X = iris.data # 特征数据
y = iris.target # 标签数据
# 划分训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)# 打印下尺寸
print(X_train.shape)
print(y_train.shape)
print(X_test.shape)
print(y_test.shape)# 归一化数据,神经网络对于输入数据的尺寸敏感,归一化是最常见的处理方式
from sklearn.preprocessing import MinMaxScaler
scaler = MinMaxScaler()
X_train = scaler.fit_transform(X_train)
X_test = scaler.transform(X_test) #确保训练集和测试集是相同的缩放# 将数据转换为 PyTorch 张量,因为 PyTorch 使用张量进行训练
# y_train和y_test是整数,所以需要转化为long类型,如果是float32,会输出1.0 0.0
X_train = torch.FloatTensor(X_train)
y_train = torch.LongTensor(y_train)
X_test = torch.FloatTensor(X_test)
y_test = torch.LongTensor(y_test)import torch
import torch.nn as nn
import torch.optim as optimclass MLP(nn.Module):def __init__(self):super(MLP,self).__init__()# 前三行是八股文,后面的是自定义的self.fc1 = nn.Linear(4,10)self.relu = nn.ReLU()self.fc2 = nn.Linear(10,3)def forward(self,x):out = self.fc1(x)out = self.relu(out)out = self.fc2(out)return out# def forward(self,x): #前向传播# x=torch.relu(self.fc1(x)) #激活函数# x=self.fc2(x) #输出层不需要激活函数,因为后面会用到交叉熵函数cross_entropy# return x# 实例化模型
model = MLP()#定义损失函数和优化器
# 分类问题使用交叉熵损失函数
criterion = nn.CrossEntropyLoss()
# 使用随机梯度下降优化器
optimizer = optim.SGD(model.parameters(),lr=0.01) #lr是学习率,学习率越大,梯度下降的速度越快,但是可能会跳过最优解,学习率越小,梯度下降的速度越慢,但是可能会找到最优解,但是需要更多的迭代次数,所以需要权衡
# 使用自适应学习率的化器
# optimizer = optim.Adam(model.parameters(),lr=0.001)#train
num_epochs = 20000
# 用于存储每个 epoch 的损失值
losses = []
for epoch in range(num_epochs):#forwardoutputs = model.forward(X_train)loss = criterion(outputs,y_train) #计算损失函数#backwardoptimizer.zero_grad() #梯度清零loss.backward() #反向传播optimizer.step() #更新参数# 记录损失值losses.append(loss.item())#print train messageif (epoch + 1) % 100 == 0:print(f'Epoch[{epoch+1}/{num_epochs}],Loss:{loss.item():.4f}')#visualize loss
import matplotlib.pyplot as pltplt.plot(range(num_epochs),losses)
plt.xlabel('Epoch')
plt.ylabel('Loss')
plt.title('Training Loss over Epochs')
plt.show()#test
with torch.no_grad(): #测试时不需要计算梯度,所以使用no_grad()outputs = model.forward(X_test) #前向传播_,predicted = torch.max(outputs.data,1) #返回最大值和索引,这里我们只需要索引,所以用_表示最大值,predicted是一个张量,里面是预测的标签,和y_test的标签进行比较,计算准确率correct = (predicted == y_test).sum().item() #计算正确的个数,.item()是将张量转换为标量accuracy = correct / y_test.size(0) #计算准确率,y_test.size(0)是测试集的大小,correct是正确的个数,所以准确率就是正确的个数除以测试集的大小print(f'Accuracy on test set:{accuracy*100:.2f}%') #输出准确率,:.2f是保留两位小数#对比随机森林模型
# 加载鸢尾花数据集
iris = load_iris()
X = iris.data # 特征数据
y = iris.target # 标签数据
# 划分训练集和测试集
X1_train, X1_test, y1_train, y1_test = train_test_split(X, y, test_size=0.2, random_state=42)from sklearn.ensemble import RandomForestClassifier #随机森林分类器
# 训练模型
model1 = RandomForestClassifier(n_estimators=100, random_state=42) #n_estimators是树的个数,random_state是随机种子,保证每次运行的结果都是一样的
model1.fit(X1_train, y1_train) #训练模型
# 预测测试集
y1_pred = model1.predict(X1_test) #预测测试集
#打印结果
from sklearn.metrics import accuracy_score, precision_score, recall_score, f1_score # 用于评估分类器性能的指标
from sklearn.metrics import classification_report, confusion_matrix #用于生成分类报告和混淆矩阵
import warnings #用于忽略警告信息
warnings.filterwarnings("ignore") # 忽略所有警告信息
print("\nRF 分类报告:")
print(classification_report(y1_test, y1_pred))
print("RF 混淆矩阵:")
print(confusion_matrix(y1_test, y1_pred)) # 打印混淆矩阵
rf_accuracy = accuracy_score(y1_test, y1_pred)
print("RF 模型评估指标:")
print(f"准确率: {rf_accuracy:.4f}")
# 计算准确率
accuracy1 = np.mean(y1_pred == y1_test)
@浙大疏锦行