该数据集包含了 150 个鸢尾花的数据,其中每个数据点都有 4 个变量(萼片长度、萼片宽度、花瓣长度、花瓣宽度)和一个目标变量(花的种类)。
该数据集最初由 R.A. Fisher 在 1936 年发布。
iris数据集的主要应用场景是分类问题,在机器学习领域中被广泛应用。
通过使用iris数据集作为样本集,我们可以训练出一个分类器,将输入的新鲜鸢尾花归类到三种品种中的某一种。
iris数据集的特征数据已经被广泛使用,也是许多特征选择算法和模型选择算法的基础数据集之一。
import torch # 导入 PyTorch 库
from torch import nn # 导入 PyTorch 的神经网络模块
from sklearn import datasets # 导入 scikit-learn 库中的 dataset 模块
from sklearn.model_selection import train_test_split # 从 scikit-learn 的 model_selection 模块导入 split 方法用于分割训练集和测试集
from sklearn.preprocessing import StandardScaler # 从 scikit-learn 的 preprocessing 模块导入方法,用于数据缩放
print("# 检查GPU是否可用")
# Check if GPU is available
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print("# 加载鸢尾花数据集")
# 加载鸢尾花数据集,这个数据集在机器学习中比较著名
iris = datasets.load_iris()
X = iris.data # 对应输入变量或属性(features),含有4个属性:花萼长度、花萼宽度、花瓣长度 和 花瓣宽度
y = iris.target # 对应目标变量(target),也就是类别标签,总共有3种分类
print("拆分训练集和测试")
# 把数据集按照80:20的比例来划分为训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2)
print("数据缩放")
# 对训练集和测试集进行归一化处理,常用方法之一是StandardScaler
scaler = StandardScaler()
X_train = scaler.fit_transform(X_train)
X_test = scaler.transform(X_test)
print("数据转tensor类型")
# 将训练集和测试集转换为PyTorch的张量对象并设置数据类型,加上to(device)可以运行在GPU上
X_train = torch.tensor(X_train).float().to(device)
y_train = torch.tensor(y_train).long().to(device)
X_test = torch.tensor(X_test).float().to(device)
y_test = torch.tensor(y_test).long().to(device)
# 定义 Transformer 模型
class TransformerModel(nn.Module):
def __init__(self, input_size, num_classes):
super(TransformerModel, self).__init__()
# 定义 Transformer 编码器,并指定输入维数和头数
self.encoder_layer = nn.TransformerEncoderLayer(d_model=input_size, nhead=1)
self.encoder = nn.TransformerEncoder(self.encoder_layer, num_layers=1)
# 定义全连接层,将 Transformer 编码器的输出映射到分类空间
self.fc = nn.Linear(input_size, num_classes)
def forward(self, x):
# 在序列的第2个维度(也就是时间步或帧)上添加一维以适应 Transformer 的输入格式
x = x.unsqueeze(1)
# 将输入数据流经 Transformer 编码器进行特征提取
x = self.encoder(x)
# 通过压缩第2个维度将编码器的输出恢复到原来的形状
x = x.squeeze(1)
# 将编码器的输出传入全连接层,获得最终的输出结果
x = self.fc(x)
return x
print("创建模型")
# 初始化 Transformer 模型
model = TransformerModel(input_size=4, num_classes=3).to(device)
print("定义损失函数和优化器")
# 定义损失函数(交叉熵损失)和优化器(Adam)
criterion = nn.CrossEntropyLoss()
optimizer = torch.optim.Adam(model.parameters(), lr=0.01)
print("训练模型")
# 训练模型,对数据集进行多次迭代学习,更新模型的参数
num_epochs = 100
for epoch in range(num_epochs):
# 前向传播计算输出结果
outputs = model(X_train)
loss = criterion(outputs, y_train)
# 反向传播,更新梯度并优化模型参数
optimizer.zero_grad()
loss.backward()
optimizer.step()
# 打印每10个epoch的loss值
if (epoch + 1) % 10 == 0:
print(f'Epoch [{epoch + 1}/{num_epochs}], Loss: {loss.item():.4f}')
print("测试模型")
# 测试模型的准确率
with torch.no_grad():
# 对测试数据集进行预测,并与真实标签进行比较,获得预测
outputs = model(X_test)
_, predicted = torch.max(outputs.data, 1)
accuracy = (predicted == y_test).sum().item() / y_test.size(0)
print(f'Test Accuracy: {accuracy:.2f}')
# 定义BP神经网络
class BPNet(torch.nn.Module):
def __init__(self, n_feature, n_hidden, n_output):
super(BPNet, self).__init__()
self.hidden = torch.nn.Linear(n_feature, n_hidden)
self.out = torch.nn.Linear(n_hidden, n_output)
def forward(self,x):
x = Fun.relu(self.hidden(x))
x = self.out(x)
return x
print("创建模型")
# 初始化 BPNet模型
model = BPNet(n_feature=4, n_hidden=10, n_output=3).to(device)
import torch # 导入 PyTorch 库
from torch import nn # 导入 PyTorch 的神经网络模块
from sklearn import datasets # 导入 scikit-learn 库中的 dataset 模块
from sklearn.model_selection import train_test_split # 从 scikit-learn 的 model_selection 模块导入 split 方法用于分割训练集和测试集
from sklearn.preprocessing import StandardScaler # 从 scikit-learn 的 preprocessing 模块导入方法,用于数据缩放
print("# 检查GPU是否可用")
# Check if GPU is available
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print("# 加载鸢尾花数据集")
# 加载鸢尾花数据集,这个数据集在机器学习中比较著名
iris = datasets.load_iris()
X = iris.data # 对应输入变量或属性(features),含有4个属性:花萼长度、花萼宽度、花瓣长度 和 花瓣宽度
y = iris.target # 对应目标变量(target),也就是类别标签,总共有3种分类
print("拆分训练集和测试")
# 把数据集按照80:20的比例来划分为训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2)
print("数据缩放")
# 对训练集和测试集进行归一化处理,常用方法之一是StandardScaler
# Standardscaler是一种预处理技术,用于将数据缩放到均值为0、方差为1的标准正态分布
scaler = StandardScaler()
X_train = scaler.fit_transform(X_train)
X_test = scaler.transform(X_test)
print("数据转tensor类型")
# 将训练集和测试集转换为PyTorch的张量对象并设置数据类型,加上to(device)可以运行在GPU上
X_train = torch.tensor(X_train).float().to(device)
y_train = torch.tensor(y_train).long().to(device)
X_test = torch.tensor(X_test).float().to(device)
y_test = torch.tensor(y_test).long().to(device)
from torch.utils.data.dataset import Dataset
# 定义MyDataset类,继承Dataset方法,并重写__getitem__()和__len__()方法
class MyDataset(Dataset):
# 初始化函数,得到数据
def __init__(self, datas, labels):
self.datas = datas
self.labels = labels
# print(df_categories_digitization)
# index是根据batchsize划分数据后得到的索引,最后将data和对应的labels进行一起返回
def __getitem__(self, index):
features = self.datas[index]
categories_digitization = self.labels[index]
return features, categories_digitization
# 该函数返回数据大小长度,目的是DataLoader方便划分,如果不知道大小,DataLoader会一脸懵逼
def __len__(self):
return len(self.labels)
# 通过MyDataset将数据进行加载,返回Dataset对象,包含data和labels
train_data = MyDataset(X_train, y_train)
test_data = MyDataset(X_test, y_test)
from torch.utils.data.dataloader import DataLoader
# 读取数据
train_dataloader = DataLoader(train_data, batch_size=4, shuffle=True, drop_last=False)
test_dataloader = DataLoader(test_data, batch_size=4, shuffle=True, drop_last=False)
# 定义 Transformer 模型
class TransformerModel(nn.Module):
def __init__(self, input_size, num_classes):
super(TransformerModel, self).__init__()
# 定义 Transformer 编码器,并指定输入维数和头数
self.encoder_layer = nn.TransformerEncoderLayer(d_model=input_size, nhead=1)
self.encoder = nn.TransformerEncoder(self.encoder_layer, num_layers=1)
# 定义全连接层,将 Transformer 编码器的输出映射到分类空间
self.fc = nn.Linear(input_size, num_classes)
def forward(self, x):
# 在序列的第2个维度(也就是时间步或帧)上添加一维以适应 Transformer 的输入格式
x = x.unsqueeze(1)
# 将输入数据流经 Transformer 编码器进行特征提取
x = self.encoder(x)
# 通过压缩第2个维度将编码器的输出恢复到原来的形状
x = x.squeeze(1)
# 将编码器的输出传入全连接层,获得最终的输出结果
x = self.fc(x)
return x
print("创建模型")
# 初始化 Transformer 模型
model = TransformerModel(input_size=4, num_classes=3).to(device)
print("定义损失函数和优化器")
# 定义损失函数(交叉熵损失)和优化器(Adam)
criterion = nn.CrossEntropyLoss()
optimizer = torch.optim.Adam(model.parameters(), lr=0.01)
print("训练模型")
# 训练模型,对数据集进行多次迭代学习,更新模型的参数
num_epochs = 100
for epoch in range(num_epochs):
for step , batch in enumerate(train_dataloader):
X_train, y_train = batch
# 前向传播计算输出结果
outputs = model(X_train)
loss = criterion(outputs, y_train)
# 反向传播,更新梯度并优化模型参数
optimizer.zero_grad()
loss.backward()
optimizer.step()
# 打印每10个epoch的loss值
if (epoch + 1) % 10 == 0:
print(f'Epoch [{epoch + 1}/{num_epochs}], Loss: {loss.item():.4f}, step:{step}')
print("测试模型")
test_pred = []
test_true = []
# 测试模型的准确率
with torch.no_grad():
# 对测试数据集进行预测,并与真实标签进行比较,获得预测
for step , batch in enumerate(train_dataloader):
X_test, y_test = batch
outputs = model(X_test)
_, predicted = torch.max(outputs.data, 1)
accuracy = (predicted == y_test).sum().item() / y_test.size(0)
print(f'step:{step}, Test Accuracy: {accuracy:.2f}')
test_true.extend(y_test.cpu().numpy().tolist())
test_pred.extend(predicted.cpu().detach().numpy().tolist())
from sklearn.metrics import accuracy_score
from sklearn.metrics import f1_score
print(f"测试集预测{test_pred}")
print(f"测试集准确{test_true}")
accuracy = accuracy_score(test_true, test_pred)
f1 = f1_score(test_true, test_pred, average = "macro")
print(f"Accuracy的值为:{accuracy}")
print(f"F1的值为:{f1}")
from sklearn.datasets import load_iris
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import train_test_split
import numpy as np
from sklearn.preprocessing import label_binarize
from sklearn.metrics import confusion_matrix, precision_score, accuracy_score,recall_score, f1_score, roc_auc_score, \
roc_curve
import matplotlib.pyplot as plt
# 加载数据集
def loadDataSet():
iris_dataset = load_iris()
X = iris_dataset.data
y = iris_dataset.target
# 将数据划分为训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2)
return X_train, X_test, y_train, y_test
# 训练Logistic模性
def trainLS(x_train, y_train):
# Logistic模型较为简单,不需要额外设置超参数即可开始训练
# Logistic生成和训练
clf = LogisticRegression()
clf.fit(x_train, y_train)
return clf
from sklearn import tree
# 训练决策树模性
def trainDT(x_train, y_train):
# DT生成和训练
clf = tree.DecisionTreeClassifier(criterion="entropy")
clf.fit(x_train, y_train)
return clf
# 训练SVM模性
from sklearn import svm
def trainSVM(x_train, y_train):
# SVM生成和训练
clf = svm.SVC(kernel='rbf', probability=True)
clf.fit(x_train, y_train)
return clf
# 测试模型
def test(model, x_test, y_test):
# 将标签转换为one-hot形式
y_one_hot = label_binarize(y_test, np.arange(3))
# 预测结果
y_pre = model.predict(x_test)
# 预测结果的概率
y_pre_pro = model.predict_proba(x_test)
# 混淆矩阵
con_matrix = confusion_matrix(y_test, y_pre)
print('confusion_matrix:\n', con_matrix)
print('accuracy:{}'.format(accuracy_score(y_test, y_pre)))
print('precision:{}'.format(precision_score(y_test, y_pre, average='micro')))
print('recall:{}'.format(recall_score(y_test, y_pre, average='micro')))
print('f1-score:{}'.format(f1_score(y_test, y_pre, average='micro')))
# 绘制ROC曲线
drawROC(y_one_hot, y_pre_pro)
def drawROC(y_one_hot, y_pre_pro):
"""
在预测结果时,为了方便后面绘制ROC曲线,需要首先将测试集的标签转化为one-hot的形式,
并得到模型在测试集上预测结果的概率值即y_pre_pro,从而传入drawROC函数完成ROC曲线的绘制。
除此外,该函数实现了输出混淆矩阵以及计算准确率、精确率、查全率以及f1-score的功能。
"""
# AUC值
auc = roc_auc_score(y_one_hot, y_pre_pro, average='micro')
# 绘制ROC曲线
fpr, tpr, thresholds = roc_curve(y_one_hot.ravel(), y_pre_pro.ravel())
plt.plot(fpr, tpr, linewidth=2, label='AUC=%.3f' % auc)
plt.plot([0, 1], [0, 1], 'k--')
plt.axis([0, 1.1, 0, 1.1])
plt.xlabel('False Postivie Rate')
plt.ylabel('True Positive Rate')
plt.legend()
plt.show()
if __name__ == '__main__':
X_train, X_test, y_train, y_test = loadDataSet()
model = trainLS(X_train, y_train)
# model = trainSVM(X_train, y_train)
# model = trainDT(X_train, y_train)
test(model, X_test, y_test)
```