2.pytorch iris data

文章目录

    • 1、数据集介绍
    • 2、 run
      • 2.1 Transformer
        • 不采用dataset dataloader形式
        • 采用dataset dataloader形式
      • 2.2 sklearn 自带模型 LR, SVM,DT

1、数据集介绍

该数据集包含了 150 个鸢尾花的数据,其中每个数据点都有 4 个变量(萼片长度、萼片宽度、花瓣长度、花瓣宽度)和一个目标变量(花的种类)。
该数据集最初由 R.A. Fisher 在 1936 年发布。

iris数据集的主要应用场景是分类问题,在机器学习领域中被广泛应用。
通过使用iris数据集作为样本集,我们可以训练出一个分类器,将输入的新鲜鸢尾花归类到三种品种中的某一种。
iris数据集的特征数据已经被广泛使用,也是许多特征选择算法和模型选择算法的基础数据集之一。
2.pytorch iris data_第1张图片

2、 run

2.1 Transformer

不采用dataset dataloader形式
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)
采用dataset dataloader形式
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}")

2.2 sklearn 自带模型 LR, SVM,DT

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)
    ```

你可能感兴趣的:(python,pytorch)