Iris 线性模型分类实验内容
编程中遇到的问题
# -*- 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)
上述代码运行结果:
如果不重新训练,会报错:
ValueError: X has 2 features per sample; expecting 4