Iris 线性模型分类实验_初学者

问题遇到的现象和发生背景

Iris 线性模型分类实验内容

  1. 将数据集按7:3 的比例随机划分为训练集和测试集,随机数生成器种子为学号后三位数,并输出训练集和测试集前10行数据;
  2. 在训练集上训练对数几率回归模型和LDA模型,以划分Setosa 和Versicolor 两个类别,模型参数自选,比较两种算法的训练时间和模型精度;
  3. 判断你认为最有区分度的两个特征,将模型在训练集和测试集上的分类结果分别二维可视化输出,并对两种算法的输出结果进行解释;
  4. 分别计算对数几率回归和LDA算法在Setosa 和Versicolor分类上的混淆矩阵,并对两种算法的输出结果进行解释.

编程中遇到的问题

  1. 实验过程中,先训练了拥有四个特征的数据集,所以训练集和测试集的数据都拥有四个特征。而我不知道如何让拥有四个特征的数据按两个特征进行二维可视化输出;
  2. 对于_X_train[y_train==0,0]_,仍不知道怎么理解。
# -*- coding: utf-8 -*-
'''
Iris鸢尾花数据集是一个经典数据集,在统计学习和机器学习领域都经常被用作示例。
数据集内包含 3 类共 150 条记录,每类各 50 个数据,
每条记录都有 4 项特征:花萼长度(sepal length)、花萼宽度(sepal width)、花瓣长度(petal length)、花瓣宽度(petal width),
可以通过这4个特征预测鸢尾花卉属于山鸢尾(Setosa),杂色鸢尾(Versicolour),维吉尼亚鸢尾(Virginica)中的哪一品种。

本文就该数据集进行简单的机器学习入门代码操作实验,
分别采用对数几率回归模型、LDA(线性判别分析)模型训练一个Setosa 和Versicolor的线性分类器,
并可视化线性分类效果,比较两种模型的训练时间、精度和分类效果。
参考代码来源:https://blog.csdn.net/baiduwaimai/article/details/106863632
'''

#数据准备和预览
import numpy as np
from sklearn import datasets
iris = datasets.load_iris()
list(iris.keys())
data=iris["data"]
feature_names=["花萼长度","花萼宽度","花瓣长度","花瓣宽度"]
target=iris["target"]
target_names=["山鸢尾","杂色鸢尾","维吉尼亚鸢尾"]
describe=iris["DESCR"]

#划分训练集
X = data[:100]#[:, 2:] 
y = target[:100]
from sklearn.model_selection import train_test_split
X_train,X_test, y_train, y_test = train_test_split(X,y,test_size=0.3, random_state=211)
print("训练集前十个数据:\n",np.c_[X_train[:10],y_train[:10]])
print("测试集前十个数据:\n",np.c_[X_test[:10],y_test[:10]])

#对数几率回归模型
import  time
from sklearn.linear_model import LogisticRegression
tic=time.time()
log_reg = LogisticRegression()
log_reg.fit(X_train, y_train)       #训练对数几率回归模型
toc=time.time()                     #获取当前CPU时钟
score=log_reg.score(X_test,y_test)  #对测试集进行测试,返回测试正确率
print("对数几率回归模型训练时间:",(toc-tic)*1e3,"ms")
print("对数几率回归模型精度:",score)

#LDA模型
from sklearn.discriminant_analysis import LinearDiscriminantAnalysis as LDA
lda = LDA()
tic=time.time()
lda.fit(X_train, y_train)
toc=time.time()
score=log_reg.score(X_test,y_test)
print("LDA训练时间:",(toc-tic)*1e3,"ms" )
print("LDA模型精度:",score)

#判断最有区分度的两个特征
import matplotlib.pyplot as plt 
from sklearn import datasets
plt.rcParams['font.family'] = 'SimHei'
k=0
for i in range(0,3):
    for j in range(i+1,4):
        X = data[:,[i,j]][:100]
        y = target[:100]
        if i==0:
            plt.subplot(3,5,2*k+1)
        else:
            plt.subplot(3,5,2*k+5)
        k+=1
        plt.scatter(X[:,0],X[:,1],c=y,marker='.')
        plt.title(feature_names[i]+"与"+feature_names[j],fontsize=9)
        plt.xlabel(feature_names[i]+"/cm")
        plt.ylabel(feature_names[j]+"/cm")

'''
由于我不知道如何让拥有四个特征的数据按两个特征进行二维可视化输出,
以解决ValueError: X has 2 features per sample; expecting 4,
所以我只好重新训练只有两个特征的数据集,并建立模型。
'''
#根据最有区分度的两个特征重复上述步骤
feature = data[:, 2:]       #最有区分度的两个特征————花瓣长度与花瓣宽度
X = feature[:100]
y = target[:100]
X_train,X_test, y_train, y_test = train_test_split(X,y,test_size=0.3, random_state=211)
tic=time.time()
log_reg = LogisticRegression()
log_reg.fit(X_train, y_train)
lda = LDA()
tic=time.time()
lda.fit(X_train, y_train)


#对数几率回归模型可视化
import matplotlib.pyplot as plt
plt.rcParams['font.family'] = 'SimHei'
x_min,x_max=[feature[:,0].min()-1,feature[:,0].max()+1]            #标定我们的绘图范围为
y_min,y_max=[feature[:,1].min()-1,feature[:,1].max()+1]            #数据集中的数据最值决定的范围下向四周拓展一个单位
x0 , y0 = np.meshgrid(np.linspace(x_min,x_max,500).reshape(-1,1),
                      np.linspace(y_min,y_max,500).reshape(-1,1))  #构建坐标网点,分别将横纵坐标集合转为列向量组
X_new = np.c_[x0.ravel(),y0.ravel()]  #把两个列向量组按列整合起来
y_proba = log_reg.predict_proba(X_new)
plt.figure()
plt.plot(X_train[y_train==0,0],X_train[y_train==0,1],"b.")      #山鸢尾训练集使用蓝色的点表示
plt.plot(X_train[y_train==1,0],X_train[y_train==1,1],"g^")      #杂色鸢尾训练集使用绿色的三角形表示
plt.plot(X_test[y_test==0,0],X_test[y_test==0,1],"b*")          #山鸢尾测试集使用蓝色的五角星表示
plt.plot(X_test[y_test==1,0],X_test[y_test==1,1],"g+")          #杂色鸢尾测试集使用绿色的加号表示
z_train=y_proba[:,1].reshape(x0.shape)  #将预测分类可能性结果为0.5的位置的等高线作为分类边界,使用黑色虚线标注
contour=plt.contourf(x0,y0,z_train,alpha=0.2,cmap=plt.cm.brg)   #将分类结果以等高线图的形式输入
plt.clabel(contour, inline=1, fontsize=12)

left_right = np.array([x_min,x_max])
boundary = -(log_reg.coef_[0][0] * left_right + log_reg.intercept_[0]) / log_reg.coef_[0][1]
plt.plot(left_right, boundary, "k--", linewidth=3)
plt.axis([x_min,x_max, y_min, y_max])
plt.title("对数几率回归模型可视化",fontsize=18)
plt.xlabel("花瓣长度",fontsize=18)
plt.ylabel("花瓣宽度",fontsize=18)
plt.legend(("山鸢尾训练集","杂色鸢尾训练集","山鸢尾测试集","杂色鸢尾测试集","分类边界"),loc='best',fontsize=18)

#LDA模型可视化
import matplotlib.pyplot as plt
plt.rcParams['font.family'] = 'SimHei'
x_min,x_max=[feature[:,0].min()-1,feature[:,0].max()+1]
y_min,y_max=[feature[:,1].min()-1,feature[:,1].max()+1]
x0 , y0 = np.meshgrid(np.linspace(x_min,x_max,500).reshape(-1,1),
                      np.linspace(y_min,y_max,500).reshape(-1,1))
X_new = np.c_[x0.ravel(),y0.ravel()]
y_proba = lda.predict_proba(X_new)
plt.figure()
plt.plot(X_train[y_train==0,0],X_train[y_train==0,1],"b.")
plt.plot(X_train[y_train==1,0],X_train[y_train==1,1],"g^")
plt.plot(X_test[y_test==0,0],X_test[y_test==0,1],"b*")
plt.plot(X_test[y_test==1,0],X_test[y_test==1,1],"g+")
z_train=y_proba[:,1].reshape(x0.shape)
contour=plt.contourf(x0,y0,z_train,alpha=0.2,cmap=plt.cm.brg)
plt.clabel(contour, inline=1, fontsize=12)

left_right = np.array([x_min,x_max])
boundary = -(lda.coef_[0][0] * left_right + lda.intercept_[0]) / lda.coef_[0][1]
plt.plot(left_right, boundary, "k--", linewidth=3)
plt.axis([x_min,x_max, y_min, y_max])
plt.title("LDA模型可视化",fontsize=18)
plt.xlabel("花瓣长度",fontsize=18)
plt.ylabel("花瓣宽度",fontsize=18)
plt.legend(("山鸢尾训练集","杂色鸢尾训练集","山鸢尾测试集","杂色鸢尾测试集","分类边界"),loc='best',fontsize=18)

#对数几率回归模型混淆矩阵
from sklearn.metrics import confusion_matrix
y_pre=log_reg.predict(X_test)
confusion=confusion_matrix(y_test,y_pre)
print("对数几率混淆矩阵:\n",confusion)
plt.figure()
plt.imshow(confusion, cmap=plt.cm.Blues)
classes = list(set(y_test))
classes.sort()
indices = range(len(confusion))
plt.title("对数几率混淆矩阵",fontsize=18)
plt.xticks(indices, classes)
plt.yticks(indices, classes)
plt.xlabel('测试集预测结果',fontsize=18)
plt.ylabel('测试集标注',fontsize=18)

#LDA模型混淆矩阵
from sklearn.metrics import confusion_matrix
y_pre=lda.predict(X_test)
confusion=confusion_matrix(y_test,y_pre)
print("LDA混淆矩阵:\n",confusion)
plt.figure()
plt.imshow(confusion, cmap=plt.cm.Blues)
classes = list(set(y_test))
classes.sort()
indices = range(len(confusion))
plt.title("LDA混淆矩阵",fontsize=18)
plt.xticks(indices, classes)
plt.yticks(indices, classes)
plt.xlabel('测试集预测结果',fontsize=18)
plt.ylabel('测试集标注',fontsize=18)

运行结果及报错内容

上述代码运行结果:

img

img

img

img

img

如果不重新训练,会报错:
ValueError: X has 2 features per sample; expecting 4