机器学习--Iris数据集的Fisher线性分类以及数据可视化技术的学习

1.Iris数据集的Fisher线性分类

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt 
path=r'./Iris.xls'
df = pd.read_csv(path, header=0)
Iris1=df.values[0:50,0:4]
Iris2=df.values[50:100,0:4]
Iris3=df.values[100:150,0:4]
m1=np.mean(Iris1,axis=0)
m2=np.mean(Iris2,axis=0)
m3=np.mean(Iris3,axis=0)
s1=np.zeros((4,4))
s2=np.zeros((4,4))
s3=np.zeros((4,4))
for i in range(0,30,1):
    a=Iris1[i,:]-m1
    a=np.array([a])
    b=a.T
    s1=s1+np.dot(b,a)    
for i in range(0,30,1):
    c=Iris2[i,:]-m2
    c=np.array([c])
    d=c.T
    s2=s2+np.dot(d,c) 
    #s2=s2+np.dot((Iris2[i,:]-m2).T,(Iris2[i,:]-m2))
for i in range(0,30,1):
    a=Iris3[i,:]-m3
    a=np.array([a])
    b=a.T
    s3=s3+np.dot(b,a) 
sw12=s1+s2
sw13=s1+s3
sw23=s2+s3
#投影方向
a=np.array([m1-m2])
sw12=np.array(sw12,dtype='float')
sw13=np.array(sw13,dtype='float')
sw23=np.array(sw23,dtype='float')
#判别函数以及T
#需要先将m1-m2转化成矩阵才能进行求其转置矩阵
a=m1-m2
a=np.array([a])
a=a.T
b=m1-m3
b=np.array([b])
b=b.T
c=m2-m3
c=np.array([c])
c=c.T
w12=(np.dot(np.linalg.inv(sw12),a)).T
w13=(np.dot(np.linalg.inv(sw13),b)).T
w23=(np.dot(np.linalg.inv(sw23),c)).T
#print(m1+m2) #1x4维度  invsw12 4x4维度  m1-m2 4x1维度
T12=-0.5*(np.dot(np.dot((m1+m2),np.linalg.inv(sw12)),a))
T13=-0.5*(np.dot(np.dot((m1+m3),np.linalg.inv(sw13)),b))
T23=-0.5*(np.dot(np.dot((m2+m3),np.linalg.inv(sw23)),c))
kind1=0
kind2=0
kind3=0
newiris1=[]
newiris2=[]
newiris3=[]
for i in range(29,49):
    x=Iris1[i,:]
    x=np.array([x])
    g12=np.dot(w12,x.T)+T12
    g13=np.dot(w13,x.T)+T13
    g23=np.dot(w23,x.T)+T23
    if g12>0 and g13>0:
        newiris1.extend(x)
        kind1=kind1+1
    elif g12<0 and g23>0:
        newiris2.extend(x)
    elif g13<0 and g23<0 :
        newiris3.extend(x)
#print(newiris1)
for i in range(29,49):
    x=Iris2[i,:]
    x=np.array([x])
    g12=np.dot(w12,x.T)+T12
    g13=np.dot(w13,x.T)+T13
    g23=np.dot(w23,x.T)+T23
    if g12>0 and g13>0:
        newiris1.extend(x)
    elif g12<0 and g23>0:
       
        newiris2.extend(x)
        kind2=kind2+1
    elif g13<0 and g23<0 :
        newiris3.extend(x)
for i in range(29,49):
    x=Iris3[i,:]
    x=np.array([x])
    g12=np.dot(w12,x.T)+T12
    g13=np.dot(w13,x.T)+T13
    g23=np.dot(w23,x.T)+T23
    if g12>0 and g13>0:
        newiris1.extend(x)
    elif g12<0 and g23>0:     
        newiris2.extend(x)
    elif g13<0 and g23<0 :
        newiris3.extend(x)
        kind3=kind3+1
#花瓣与花萼的长度散点图
plt.scatter(df.values[:50, 3], df.values[:50, 1], color='red', marker='o', label='setosa')
plt.scatter(df.values[50:100, 3], df.values[50: 100, 1], color='blue', marker='x', label='versicolor')
plt.scatter(df.values[100:150, 3], df.values[100: 150, 1], color='green', label='virginica')
plt.xlabel('petal length')
plt.ylabel('sepal length')
plt.title("花瓣与花萼长度的散点图")
plt.rcParams['font.sans-serif']=['SimHei'] #显示中文标签
plt.rcParams['axes.unicode_minus']=False
plt.legend(loc='upper left')
plt.show()

#花瓣与花萼的宽度度散点图
plt.scatter(df.values[:50, 4], df.values[:50, 2], color='red', marker='o', label='setosa')
plt.scatter(df.values[50:100, 4], df.values[50: 100, 2], color='blue', marker='x', label='versicolor')
plt.scatter(df.values[100:150, 4], df.values[100: 150, 2], color='green', label='virginica')
plt.xlabel('petal width')
plt.ylabel('sepal width')
plt.title("花瓣与花萼宽度的散点图")
plt.legend(loc='upper left')
plt.show()

correct=(kind1+kind2+kind3)/60
print("样本类内离散度矩阵S1:",s1,'\n')
print("样本类内离散度矩阵S2:",s2,'\n')
print("样本类内离散度矩阵S3:",s3,'\n')
print('-----------------------------------------------------------------------------------------------')
print("总体类内离散度矩阵Sw12:",sw12,'\n')
print("总体类内离散度矩阵Sw13:",sw13,'\n')
print("总体类内离散度矩阵Sw23:",sw23,'\n')
print('-----------------------------------------------------------------------------------------------')
print('判断出来的综合正确率:',correct*100,'%')

结果图:
在这里插入图片描述
在这里插入图片描述

2.数据可视化技术的学习

1.数据集介绍

Iris数据集是常用的分类实验数据集,由Fisher, 1936收集整理。Iris也称鸢尾花卉数据集,是一类多重变量分析的数据集。数据集包含150个数据集,分为3类,每类50个数据,每个数据包含4个属性。可通过花萼长度,花萼宽度,花瓣长度,花瓣宽度4个属性预测鸢尾花卉属于(Setosa,Versicolour,Virginica)三个种类中的哪一类。

该数据集包含了5个属性:

Sepal.Length(花萼长度),单位是cm;

Sepal.Width(花萼宽度),单位是cm;

Petal.Length(花瓣长度),单位是cm;

Petal.Width(花瓣宽度),单位是cm;

种类:Iris Setosa(山鸢尾)、Iris Versicolour(杂色鸢尾),以及Iris Virginica(维吉尼亚鸢尾)。

2.观看数据前5行

import pandas as pd

import warnings 
warnings.filterwarnings("ignore")
import seaborn as sns
import matplotlib.pyplot as plt
sns.set(style="white", color_codes=True)

# 读入数据
iris = pd.read_csv("./Iris.csv") # the iris dataset is now a Pandas DataFrame

# 看下数据前5行
iris.head()
Id SepalLengthCm SepalWidthCm PetalLengthCm PetalWidthCm Species
0 1 5.1 3.5 1.4 0.2 Iris-setosa
1 2 4.9 3.0 1.4 0.2 Iris-setosa
2 3 4.7 3.2 1.3 0.2 Iris-setosa
3 4 4.6 3.1 1.5 0.2 Iris-setosa
4 5 5.0 3.6 1.4 0.2 Iris-setosa
#查看数据整体信息
iris.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 150 entries, 0 to 149
Data columns (total 6 columns):
Id               150 non-null int64
SepalLengthCm    150 non-null float64
SepalWidthCm     150 non-null float64
PetalLengthCm    150 non-null float64
PetalWidthCm     150 non-null float64
Species          150 non-null object
dtypes: float64(4), int64(1), object(1)
memory usage: 7.2+ KB
import seaborn as sns
import matplotlib.pyplot as plt
#sns初始化
sns.set()

## 5.描述性统计
iris.describe()
Id SepalLengthCm SepalWidthCm PetalLengthCm PetalWidthCm
count 150.000000 150.000000 150.000000 150.000000 150.000000
mean 75.500000 5.843333 3.054000 3.758667 1.198667
std 43.445368 0.828066 0.433594 1.764420 0.763161
min 1.000000 4.300000 2.000000 1.000000 0.100000
25% 38.250000 5.100000 2.800000 1.600000 0.300000
50% 75.500000 5.800000 3.000000 4.350000 1.300000
75% 112.750000 6.400000 3.300000 5.100000 1.800000
max 150.000000 7.900000 4.400000 6.900000 2.500000
iris.describe(include =['O']).T
count unique top freq
Species 150 3 Iris-virginica 50

总数150, 3个种类, 最大频数为50, 也就是每种都为50个. 注意top里的指的不是Iris-versicolor最多, 是在频数相同的基础上按照字符串长度进行排名.

iris.Species.value_counts()
virginica     50
versicolor    50
setosa        50
Name: Species, dtype: int64

通过以上, 大致了解数据的基本信息, 现想把Species特征中的’Iris-'字符去掉, 进入特征工程环节.

3.特征工程

1.数据清洗

去掉Species特征中的’Iris-'字符.

#第一种方法: 替换
#第二种方法: 分割
iris['Species']= iris.Species.apply(lambda x: x.split('-')[0])
iris.Species.unique()
array(['setosa', 'versicolor', 'virginica'], dtype=object)

2.数据可视化

Seaborn是一个python的可视化库, 它基于matplotlib, 这使得它能与pandas紧密结合, 并且提供了高级绘图界面, 能更方便地完成探索性分析.

我想在这个项目上对seaborn多加练习, 因此, 会对这部分内容着重介绍.

import seaborn as sns
import matplotlib.pyplot as plt
#sns初始化
sns.set()
#设置散点图x轴与y轴以及data参数
sns.relplot(x='SepalLengthCm', y='SepalWidthCm', data = iris)
plt.title('SepalLengthCm and SepalWidthCm data analysize')

在这里插入图片描述

花萼的长度和宽度在散点图上分了两个簇, 而且两者各自都有一定的关系. 鸢尾花又分为三个品种, 不妨看看关于这三个品种的分布.

#hue表示按照Species对数据进行分类, 而style表示每个类别的标签系列格式不一致.
sns.relplot(x='SepalLengthCm', y='SepalWidthCm', hue='Species', style='Species', data=iris )
plt.title('SepalLengthCm and SepalWidthCm data by Species')

在这里插入图片描述

可以看到setosa这种花的花萼长度和宽度有明显的线性关系, 当然其他两种也存在一定的关系, 花萼的属性看完了, 看下花瓣的:

#花瓣长度与宽度分布散点图
sns.relplot(x='PetalLengthCm', y='PetalWidthCm', hue='Species', style='Species', data=iris )
plt.title('PetalLengthCm and PetalWidthCm data by Species')

在这里插入图片描述

花的品种和花瓣的长度, 宽度之间存在一定的关系

另外, 还可以对比花萼与花瓣的长度, 花萼与花瓣的宽度之间的关系.

#花萼与花瓣长度分布散点图
# sns.relplot(x='SepalLengthCm', y='PetalLengthCm', hue='Species', style='Species', data=df_Iris )
#plt.title('SepalLengthCm and PetalLengthCm data by Species')
#花萼与花瓣宽度分布散点图
sns.relplot(x='SepalWidthCm', y='PetalWidthCm', hue='Species', style='Species', data=iris )
plt.title('SepalWidthCm and PetalWidthCm data by Species')

在这里插入图片描述

花萼的长度与花瓣的宽度, 花萼的宽度与花瓣的长度之间应当也存在某种关系:

#花萼的长度与花瓣的宽度分布散点图
# sns.relplot(x='SepalLengthCm', y='PetalWidthCm', hue='Species', style='Species', data=df_Iris )
#plt.title('SepalLengthCm and PetalWidthCm data by Species')
#花萼的宽度与花瓣的长度分布散点图
sns.relplot(x='SepalWidthCm', y='PetalLengthCm', hue='Species', style='Species', data=iris )
plt.title('SepalWidthCm and PetalLengthCm data by Species') 

在这里插入图片描述

Id编号与花萼长度, 花萼宽度, 花瓣长度, 花瓣宽度之间有没有关系呢:

#花萼长度与Id之间关系图
sns.relplot(x="Id", y="SepalLengthCm",hue="Species", style="Species",kind="line", data=iris)
plt.title('SepalLengthCm and Id data analysize')
#花萼宽度与Id之间关系图
sns.relplot(x="Id", y="SepalWidthCm",hue="Species", style="Species",kind="line", data=iris)
plt.title('SepalWidthCm and Id data analysize')
#花瓣长度与Id之间关系图
sns.relplot(x="Id", y="PetalLengthCm",hue="Species", style="Species",kind="line", data=iris)
plt.title('PetalLengthCm and Id data analysize')
#花瓣宽度与Id之间关系图
sns.relplot(x="Id", y="PetalWidthCm",hue="Species", style="Species",kind="line", data=iris)
plt.title('PetalWidthCm and Id data analysize')

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

3.jointplot

sns.jointplot(x='SepalLengthCm', y='SepalWidthCm', data=iris)
sns.jointplot(x='PetalLengthCm', y='PetalWidthCm', data=iris)

在这里插入图片描述

在这里插入图片描述

对于频数的值, 在散点图上数点的话, 显然效率太低, 还易出错, 下面引出distplot

4.distplot

#绘制直方图, 其中kde=False表示不显示核函数估计图,这里为了更方便去查看频数而设置它为False.
# sns.distplot(df_Iris.SepalLengthCm,bins=8, hist=True, kde=False)
# sns.distplot(df_Iris.SepalWidthCm,bins=13, hist=True, kde=False)
# sns.distplot(df_Iris.PetalLengthCm, bins=5, hist=True, kde=False)
sns.distplot(iris.PetalWidthCm, bins=5, hist=True, kde=False)

在这里插入图片描述

前面我们已经通过describe()方法计算出四个属性所对应的四分位数, 最大值以及最小值等统计量. 这些均是以表格的形式展示, 我们下面就介绍怎么以图样的形式展示四分位数.

5.boxplot

boxplot所绘制的就是箱线图, 它能显示出一组数据的最大值, 最小值, 四分位数以及异常点.

对于异常点的定义: 区间[Q1-1.5IQR, Q3+1.5IQR]之外的点, 其中Q1下四分位数(25%), Q3上四分位数(75%), IQR=Q3-Q1

在seaborn.boxplot中, 箱线图的画法分两种情况

如果数据中无异常点, 那么箱线图的下边缘就是数据中的最小值, 上边缘就是数据中的最大值

如果数据中有异常点, 那么箱线图的下边缘Limit1指的是区间[Q1-1.5IQR, Q3+1.5IQR]内的最小值, 上边缘Limit2指的是区间内的最大值

#比如数据中的SepalLengthCm属性
sns.boxplot(x='SepalLengthCm', data=iris)
#比如数据中的SepalWidthCm属性
sns.boxplot(x='SepalWidthCm', data=iris)

在这里插入图片描述

为了更直观地对比四个属性之间的关系, 我将四个属性对应的数值合并在新的DataFrame Iris中.

import numpy as np
#对于每个属性的data创建一个新的DataFrame
Iris1 = pd.DataFrame({"Id": np.arange(1,151), 'Attribute': 'SepalLengthCm', 'Data':iris.SepalLengthCm, 'Species':iris.Species})
Iris2 = pd.DataFrame({"Id": np.arange(151,301), 'Attribute': 'SepalWidthCm', 'Data':iris.SepalWidthCm, 'Species':iris.Species})
Iris3 = pd.DataFrame({"Id": np.arange(301,451), 'Attribute': 'PetalLengthCm', 'Data':iris.PetalLengthCm, 'Species':iris.Species})
Iris4 = pd.DataFrame({"Id": np.arange(451,601), 'Attribute': 'PetalWidthCm', 'Data':iris.PetalWidthCm, 'Species':iris.Species})
#将四个DataFrame合并为一个.
Iris = pd.concat([Iris1, Iris2, Iris3, Iris4])
#绘制箱线图
sns.boxplot(x='Attribute', y='Data', data=Iris)

在这里插入图片描述

就中位数来说, SepalLenthCm > PetalLengthCm > SepalWidthCm > PetalWidthCm; 就波动程度来说, PetalLengthCm > PetalWidthCm > SepalLengthCm > SepalWidthCm; 就异常值来说, 只有SepalWidthCm中存在异常值.

将鸢尾花的三种种类再加入到箱线图中:

sns.boxplot(x='Attribute', y='Data',hue='Species', data=Iris)

在这里插入图片描述

6.violinplot

violinplot绘制的是琴图, 是箱线图与核密度图的结合体, 既可以展示四分位数, 又可以展示任意位置的密度.

sns.violinplot(x='Attribute', y='Data', hue='Species', data=Iris )

在这里插入图片描述

上图中具体细节显示不是很明显, 对于PetalWidthCm都有些模糊了, 下面将拆分成四个小图, 另外为了和箱线图对比, 将箱线图也绘制出来.

#花萼长度
# sns.boxplot(x='Species', y='SepalLengthCm', data=df_Iris)
# sns.violinplot(x='Species', y='SepalLengthCm', data=df_Iris)
# plt.title('SepalLengthCm data by Species')
#花萼宽度
# sns.boxplot(x='Species', y='SepalWidthCm', data=df_Iris)
# sns.violinplot(x='Species', y='SepalWidthCm', data=df_Iris)
# plt.title('SepalWidthCm data by Species')
#花瓣长度
# sns.boxplot(x='Species', y='PetalLengthCm', data=df_Iris)
# sns.violinplot(x='Species', y='PetalLengthCm', data=df_Iris)
# plt.title('PetalLengthCm data by Species')
#花瓣宽度
sns.boxplot(x='Species', y='PetalWidthCm', data=iris)
sns.violinplot(x='Species', y='PetalWidthCm', data=iris)
plt.title('PetalWidthCm data by Species')

在这里插入图片描述

7.violinplot

sns.violinplot(x='Attribute', y='Data', hue='Species', data=Iris )

在这里插入图片描述

上图中具体细节显示不是很明显, 对于PetalWidthCm都有些模糊了, 下面将拆分成四个小图, 另外为了和箱线图对比, 将箱线图也绘制出来.

#花萼长度
# sns.boxplot(x='Species', y='SepalLengthCm', data=df_Iris)
# sns.violinplot(x='Species', y='SepalLengthCm', data=df_Iris)
# plt.title('SepalLengthCm data by Species')
#花萼宽度
# sns.boxplot(x='Species', y='SepalWidthCm', data=df_Iris)
# sns.violinplot(x='Species', y='SepalWidthCm', data=df_Iris)
# plt.title('SepalWidthCm data by Species')
#花瓣长度
# sns.boxplot(x='Species', y='PetalLengthCm', data=df_Iris)
# sns.violinplot(x='Species', y='PetalLengthCm', data=df_Iris)
# plt.title('PetalLengthCm data by Species')
#花瓣宽度
sns.boxplot(x='Species', y='PetalWidthCm', data=iris)
sns.violinplot(x='Species', y='PetalWidthCm', data=iris)
plt.title('PetalWidthCm data by Species')

在这里插入图片描述

8.pairplot

#删除Id特征, 绘制分布图
sns.pairplot(iris.drop('Id', axis=1), hue='Species')
#保存图片, 由于在jupyter notebook中太大, 不能一次截图
plt.savefig('pairplot.png')
plt.show()

在这里插入图片描述

综上, 花萼的长度, 花萼的宽度, 花瓣的长度, 花瓣的宽度与花的种类之间均存在一定的相关性, 且对于这三个种类的分布, satosa在任何一种分布中较其他两者集中; 就同一种花的平均水平来看, 其花萼的长度最长, 花瓣的宽度最短; 就同一属性的平均水平来看, 三种花在除了花萼的宽度外的属性中平均水平均表现为: Virginica > versicolour > setosa.

from sklearn.model_selection import train_test_split
from sklearn.tree import DecisionTreeClassifier

X = iris[['SepalLengthCm','SepalWidthCm','PetalLengthCm','PetalWidthCm']]
y = iris['Species']
#将数据按照8:2的比例随机分为训练集, 测试集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2)
#初始化决策树模型
dt = DecisionTreeClassifier()
#训练模型
dt.fit(X_train, y_train)
#用测试集评估模型的好坏
dt.score(X_test, y_test)
0.9666666666666667

在测试集上准确率达到97%,也还不错


参考地址:
------------博客园-----------

原创文章 31 获赞 60 访问量 3093

猜你喜欢

转载自blog.csdn.net/qq_40651017/article/details/105926783
今日推荐