一、项目介绍
这个项目是我们《数据分析与机器学习这门课程》的实验一,数据集由老师提供,是csv文件格式。鸢尾花数据集是机器学习入门的一个经典的数据集,本项目通过花萼长度,花萼宽度,花瓣长度,花瓣宽度4个属性预测鸢尾花卉属于(Setosa,Versicolour,Virginica)三个种类中的哪一类。是一个三分类的监督学习问题。我们在此数据集上构造多个机器学习模型,并评估他们学习效果的好坏。
二、数据预处理
首先做的是缺失值的判断与填充,在这里总结一下查看缺失值的方法:
- df.isnull()元素级别的判断,把所有元素的缺失值情况都列出来,元素为空就显示NA或True,反之显示False(不常用)
- df.isnull().any(),列级别的判断,判断每列的缺失值情况。
- df[df.isnull().values==True],只显示存在缺失值的行列,清楚的确定缺失值的位置。
#从文件中读取数据
#查看缺失值,isnull.values==True只显示有缺失值的行列
import pandas as pd
iris=pd.read_csv(r"D:\QQ\782869251\FileRecv\鸢尾花分类\iris.csv",engine='python')
iris[iris.isnull().values==True]
#用平均值填补缺失值
iris["Sepal.Length"]=iris['Sepal.Length'].fillna(iris['Sepal.Length'].mean())
iris["Sepal.Width"]=iris["Sepal.Width"].fillna(iris["Sepal.Width"].mean())
iris["Petal.Length"]=iris["Petal.Length"].fillna(iris["Petal.Length"].mean())
iris["Petal.Width"]=iris["Petal.Width"].fillna(iris["Petal.Width"].mean())
#查看前五行数据的情况
iris.head()
#describe()查看样本数据的基本统计量,如总数,均值,标准差,最值等
iris.describe()
接下来,借助图形更好的观察数据的分布情况,查看变量两两间的关系。这里用到的seaborns在matplotlib基础上进行了更高级的api封装,使绘图变得更容易,不需要大量的调整,就可以绘出精致的图片
#violinplot小提琴图显示数据分布及概率密度
#通过小提琴图可以看出,当前数据分布在哪一个区间内,同时在这个区间的分布密度,分布密度最大的在那个位置。
import matplotlib.pyplot as plt
plt.figure(figsize=(10, 10))
for column_index, column in enumerate(iris.columns):
if column == 'Species':
continue
plt.subplot(2, 2, column_index + 1)
sns.violinplot(x='Species', y=column, data=iris)
三、构建分类器
先简单使用K近邻(KNeighborsClassifier),支持向量机(SupportVectoeMachine)构造分类器并进行模型的评估,再详细介绍决策时算法DecisionTreeClassifier的使用
K近邻很奇怪的是,改变参数n_neighbors的数量1-9,准确率一直维持在0.9777不变
#KNN
from sklearn.neighbors import KNeighborsClassifier
knn=KNeighborsClassifier(n_neighbors=5)
knn.fit(train_inputs,train_classes)
knn.score(test_inputs,test_classes)
SVM也是,跑过一次模型之后,再改变参数,准确率一直不变
from sklearn import svm
classifier=svm.SVC(kernel='rbf',gamma=0.1,decision_function_shape='ovo',C=0.8)
classifier.fit(train_inputs,train_classes)
classifier.score(test_inputs,test_classes)
- 下面详细介绍决策树算法
- 决策树的参数:
classsklearn.tree.DecisionTreeClassifier(criterion=’gini’, splitter=’best’, max_depth=None, min_samples_split=2, min_samples_leaf=1, min_weight_fraction_leaf=0.0, max_features=None, random_state=None, max_leaf_nodes=None, min_impurity_decrease=0.0, min_impurity_split=None, class_weight=None, presort=False)
criterion用来决定不纯度的计算方法,有"entropy"信息熵和"gini"基尼系数两种splitter特征划分点选择方法,可以是"best"或random,一般样本量不大时选择best,样本量过大,可以用random
max_depth限制树的最大深度,建议从=3开始尝试,看看拟合效果再决定是否增加设定深度。
min_samples_split节点再划分所需最少样本数。默认是2。
min_samples_leaf叶子节点所需最少样本数。如果达不到这个阈值,则同一父节点的所有叶子节点均被剪枝,这是一个防止过拟合的参数。建议从=5开始使用。
max_featues划分考虑的最大特征数,用作树的精修
min_impurity_decrease/min_impurity_split: 划分最需最小不纯度
class_weight:类别权重。在样本有较大缺失值或类别偏差较大时可以选择,防止决策树向类别过大的样本倾斜。可设定为"balanced"
min_weight_fraction_leaf: 叶子节点所有样本权重和。搭配class_weight使用,如果低于阈值,则会和兄弟结点一起呗减掉。
#决策树,默认参数
from sklearn.tree import DecisionTreeClassifier
decision_tree_classifier=DecisionTreeClassifier()
decision_tree_classifier.fit(train_inputs,train_classes)
decision_tree_classifier.score(test_inputs,test_classes)
由于一次结果的代表性不强,所以选择交叉验证,并取平均值作为最终结果
from sklearn.model_selection import cross_val_score
import numpy as np
cv_scores=cross_val_score(decision_tree_classifier,all_inputs,all_classes,cv=10)
np.mean(cv_scores)
GraidSerachCV网格搜索.待调节的参数很多,参数之间的组合也很多,使用sklearn的GridSearchCV在指定范围内自动搜索具有不同超参数的不同模型的组合
from sklearn.model_selection import GridSearchCV
params={"max_depth":[1,2,3,4,5],"max_features":[1,2,3,4]}
grid_search=GridSearchCV(decision_tree_classifier,params,cv=10)
grid_search.fit(train_inputs,train_classes)
print(grid_search.best_score_)
print(grid_search.best_params_)
四、构造神经网络模型进行分类
主要流程如下:搭建网络结构(add)→将搭建好的模型进行编译(compile)→对训练数据进行拟合训练(train)→打印出网络的结构和参数估计(summary)→对训练好的模型进行评估(evaluate)
#使用sklearn的LabelEncoder库,将all_classes字符串数组转化为整数数组
from sklearn.preprocessing import LabelEncoder
X=iris[iris.columns.drop('Species')].values
y=iris['Species'].values
encoder=LabelEncoder()
y1=encoder.fit_transform(y)
#再将y1转成神经网络需要的数组结构
Y=pd.get_dummies(y1).values
划分训练集和测试集
from sklearn.model_selection import train_test_split
train_inputs,test_inputs,train_classes,test_classes=train_test_split(X,Y,test_size=0.3,random_state=1)
使用Sequential创建神经网络模型,模型一共四层。损失函数使用"categorial_crossentropy"(比较适用于3种以上的分类情况),指定metrics=['accuracy'],会在训练结束后计算训练数据在模型上的准确率
from keras.models import Sequential
from keras.layers import Dense
from keras.optimizers import Adam
#类的实例化
model = Sequential()
#全连接层model.add(Dense(神经元个数,激活函数))
model.add(Dense(10, input_shape=(4,), activation='relu'))
model.add(Dense(8, activation='relu'))
model.add(Dense(6, activation='relu'))
model.add(Dense(3, activation='softmax'))
#model.compile(优化器,损失函数,准确率)
model.compile(Adam(lr=0.04), 'categorical_crossentropy', metrics=['accuracy'])
#model.summary打印出网络的结果和参数统计
model.summary()
#指定epochs=100,训练数据会在模型中训练100次
model.fit(train_inputs,train_classes,epochs=100)
#使用模型进行预测
y_pred=model.predict(test_inputs)
浮点类型的数据不方便理解,所有使用np.argmax将数据转为整数数组
np.armax其实是取出最大值对应的索引,对于二维数组来说有两个索引方向,1代表按行搜索最大值
import numpy as np
Y_pred=np.argmax(y_pred,axis=1)
Y_test=np.argmax(test_classes,axis=1)
#模型评估
from sklearn.metrics import classification_report
report=classification_report(Y_test,Y_pred)
report