# # -*- coding:utf-8 -*- import os import pandas as pd import requests """ 先下载iris.data数据集,并写入path目录。实际上下载的是.csv文件,但是通过pandas操作,给 文件添加了一列标题。读出来的结果类似Excel,pandas其实就是操作的行和列,数据列Series,表格DataFrame. """ PATH = "D:/Python-lianxi" r = requests.get('https://archive.ics.uci.edu/ml/machine-learning-databases/iris/iris.data') with open(PATH + 'iris.data','w') as f : f.write(r.text) os.chdir(PATH) df = pd.read_csv(PATH + 'iris.data',names=['sepal length','sepal width','petal length','petal width','class']) # print(df.head()) #打印出iris数据 """ 下面看下pandas的操作 """ # print(df['sepal length']) #通过列名,从数据框中选择某一列。如果想只看其中某几个数据,可以使用切片。 # print(df.ix[:3,:2]) #使用.ix标注和Python列表切片的预防,能够选择该数据框中的一小片。 #下面使用列表迭代器选择width的所有列 # print(df.ix[:3,[x for x in df.columns if 'width' in x]]) """ 以上是基于其在数据框中的位置,选择数据分片。下面使用根据某些特定条件,来选择数据的一个子集。 """ # print(df['class'].unique()) # print(df[df['class']== 'Iris-virginica']) #查看分类是Iris-virginica的数据 # print(df.count()) #统计总有多少行数据 # print(df[df['class'] == 'Iris-virginica'].count()) #统计分类为Iris-virginica的数据 """ 以上打印的数据来看,在左侧的索引保留了原始行号。可以将这些数据保存为一个新的数据框并且重置索引。 """ # virginica = df[df['class'] == 'Iris-virginica'].reset_index(drop= True) # print(virginica) """ 也可以通过在某一列上放置条件来选择数据 """ # print(df[(df['class'] == 'Iris-virginica')&(df['petal width']>2.2)]) #只选择分类为Iris-virginica并花瓣宽度大于2.2的数据 # print(df.describe()) #使用describe方法,收集各相关列的描述性统计信息,类别列不算 # print(df.describe(percentiles=[.20,.40,.80,.90,.95])) #自定义百分比数据 """ 检查各特征是否有相关性,用.corr方法,一般情况系数为正的,表示相关性强一点,负的相关性弱 """ # print(df.corr()) #可以查看每个行-列对中的Pearson系数,可以查看秩相关系数 # print(df.corr(method="spearman")) # print(df.corr(method="kendall")) """ 以上代码是学习如果选择数据框的某一部分数据,并且从数据中获取汇总统计信息。 但是只看这些数字并不能直观的看出结论,这个是个可视化就登场啦! """ import matplotlib.pyplot as plt plt.style.use('ggplot') import numpy as np #下面开始生产第一个图 # fig,ax = plt.subplots(figsize=(6,4)) #创建宽度为6和高度为4 的插图 # ax.hist(df['petal width'],color='black') #调用.hist并传人数据,绘制直方图,柱子颜色为黑色 # ax.set_ylabel('Count',fontsize=12) #分别在X轴,Y轴上放置标签,最后一行设置标题。还设置了字体大小 # ax.set_xlabel('Width',fontsize=12) # plt.title('Iris Petal Width',fontsize=14,y=1.01) # plt.show() #也可以为每一列生成一个直方图 # fig, ax = plt.subplots(2,2, figsize=(6,4)) # # ax[0][0].hist(df['petal width'], color='black'); # ax[0][0].set_ylabel('Count', fontsize=12) # ax[0][0].set_xlabel('Width', fontsize=12) # ax[0][0].set_title('Iris Petal Width', fontsize=14, y=1.01) # # ax[0][1].hist(df['petal length'], color='black'); # ax[0][1].set_ylabel('Count', fontsize=12) # ax[0][1].set_xlabel('Lenth', fontsize=12) # ax[0][1].set_title('Iris Petal Lenth', fontsize=14, y=1.01) # # ax[1][0].hist(df['sepal width'], color='black'); # ax[1][0].set_ylabel('Count', fontsize=12) # ax[1][0].set_xlabel('Width', fontsize=12) # ax[1][0].set_title('Iris Sepal Width', fontsize=14, y=1.01) # # ax[1][1].hist(df['sepal length'], color='black'); # ax[1][1].set_ylabel('Count', fontsize=12) # ax[1][1].set_xlabel('Length', fontsize=12) # ax[1][1].set_title('Iris Sepal Length', fontsize=14, y=1.01) # # plt.tight_layout() #该方法可以自动调整子插图,排版更好看一点 # plt.show() #也可以使用散点图 # fig,ax = plt.subplots(figsize=(6,6)) # ax.scatter(df['petal width'],df['petal length'],color='green') # ax.set_xlabel('Petal Width') # ax.set_ylabel('Petal Length') # ax.set_title('Petal Scatterplot') # plt.show() # 也可以添加多个子插图,检查每个方面的数据情况 # fig,ax = plt.subplots(figsize=(6,6)) # ax.plot(df['petal length'],color='blue') # ax.set_xlabel('Specimen Number') # ax.set_ylabel('Petal Length') # ax.set_title('Petal Length plot') # plt.show() #以上线图,可以清楚的看出每个类别存在鲜明的长度差别-样本数据集在每个类别拥有50个排序的样例, #得出花瓣长度很可能是用与区分类别的有用特征 """ 条形图 """ # fig ,ax = plt.subplots(figsize=(6,6)) # bar_width = 0.6 # labels = [x for x in df.columns if 'length' in x or 'width' in x ] # ver_y = [df[df['class']=='Iris-versicolor'][x].mean() for x in labels] # vir_y = [df[df['class'] =='Iris-virginica'][x].mean() for x in labels] # set_y = [df[df['class']=='Iris-setosa'][x].mean() for x in labels] # x = np.arange(len(labels)) # ax.bar(x,vir_y,bar_width,bottom=set_y,color='darkgrey') # ax.bar(x,set_y,bar_width,bottom=ver_y,color='red') # ax.bar(x,ver_y,bar_width,color='black') # ax.set_xticks(x + (bar_width/2)) # ax.set_xticklabels(labels,rotation=-70,fontsize=12) # ax.set_title('Mean Feature Measurement By Class',y=1.01) # ax.legend(['Virginica','Setosa','Versicolor']) # plt.show() """ 为了生成条形图,将x和y 的值传递给bar方法。 """ """ 接下来进行可视化展示。Seabor库 """ import matplotlib.pyplot as plt import seaborn as sns sns.pairplot(df,hue="class") # plt.show() #由于seaborn是建立在matplotlib上的,可以直接使用show函数 # fig ,ax = plt.subplots(2,2,figsize=(7,7)) # sns.set(style='white',palette='muted') # sns.violinplot(x=df['class'],y=df['sepal length'],ax=ax[0,0]) # sns.violinplot(x=df['class'],y=df['sepal width'],ax=ax[0,1]) # sns.violinplot(x=df['class'],y=df['petal length'],ax=ax[1,0]) # sns.violinplot(x=df['class'],y=df['petal width'],ax=ax[1,1]) # fig.suptitle('Violin Plots',fontsize=16,y=1.03) # for i in ax.flat: # plt.setp(i.get_xticklabels(),rotation=-90) # fig.tight_layout() # plt.show() # 上图展示了特征的分布情况。类别irissetosa的花瓣长度高度聚集在1-2厘米,类别iris-virginica分散 # 在4-7厘米之间。 """ 以上主要是检查数据的展示,下面就要开始操作和处理数据了。 """ #首先看下map,map方法适用序列数据 #下面展示将鸢尾花分类类型替换,原来的分类名称太长了,不方便 # df['class'] = df['class'].map({'Iris-setosa':'SET','Iris-virginica':'VIR','Iris-versicolor':'VER'}) # print(df) #可以看到类型都替换成新的名称 """ 上面的操作,将现有的class列的每个值都运行了map方法,由于每个值都能在Python的字典 中找到, 呗添加到被返回的序列。 """ #下面展示apply的方法,apply也是可以操作数据框的方法。根据花瓣宽度创建新的列,之前看到花瓣宽度平均值是1.3 #现在创建新列宽花瓣,包含一个基于petal width列的二进制值,如果花瓣宽度等于或宽于中值,编码为1,小鱼中值, #编码为0.下面用apply来实现。 # df['wide petal'] = df['petal width'].apply(lambda v:1 if v>=1.3 else 0) # print(df) #基于petal area创建一个新的特征 # df['petal area'] = df.apply(lambda r:r['petal length']*r['petal width'],axis=1) #在整个数据框中调用apply,axis=1表示调用函数,axis=0表示该函数对列进行操作。以上操作,每列都被顺序的处理, #petal length 和petalwidth相乘,得到petal area # print(df) #applymap # df.applymap(lambda v:np.log(v) if isinstance(v,float) else v) # print(df) #groupby # df.groupby('class').mean() # df.groupby('class').describe() # df.groupby('petal width')['class'].unique().to_frame() df.groupby('class')['petal width'].agg({'detal':lambda x :x.max()-x.min(),'max':np.max,'min':np.min}) # print(df) """ 建模和评估 """ #先看下花萼宽度和长度的关系 fig,ax = plt.subplots(figsize=(7,7)) ax.scatter(df['sepal width'][:50],df['sepal length'][:50]) ax.set_ylabel('Sepal Length') ax.set_xlabel('Sepal Width') ax.set_title('Setosa Sepal Width vs.Sepal Length',fontsize=14,y=1.02) # plt.show() """ 由上图看出,似乎有一个正向的线性关系,随着花萼的宽度增加,花萼的长度也会增加。 接下来实验一下线性回归模型,预估这种关系的强度。 """ import statsmodels.api as sm y = df['sepal length'][:50] x = df['sepal width'][:50] X = sm.add_constant(x) results = sm.OLS(y,X).fit() # print(results.summary()) """ 执行结果是 简单的回归模型结果。线性回归模型格式为Y=B0+B1X,其中B0为截距,B1是回归系数, sepal length=2.6447+0.6909*sepal width.根据结果可以看到R2值尾58,还可以接受。P值就不太正常了。 """ #下面用结果对象来绘制回归线 fig,ax = plt.subplots(figsize=(7,7)) ax.plot(x,results.fittedvalues,label ='regression line') ax.scatter(x,y,label='data point',color='r') ax.set_ylabel('Sepal Length') ax.set_xlabel('Sepal Width') ax.set_title('Setosa Sepal Width vs.Sepal Length',fontsize=14,y=1.02) ax.legend(loc=2) # plt.show() """ scikit-learn库包含分类、回归、聚类、降维、模型选择和预处理,是非常全的库。 下面使用iris数据建立一个分类器,然后学习如何使用scikit-learn评估得到的模型。 """ """ 用scikit-learn打造机器学习模型的第一步,是要理解数据应如何构造。 独立变量该是数字型的n*m纬的矩阵x、一个因变量y和n*1维的向量。该y向量应该可以是连续的数字,也可以是离散的数字, 还可以是离散的字符串类型。然后将这些向量传递到指定分类器的.fit()方法。 """ """ 以下的代码,先建立、训练一个分类器,在iris数据集上具有95%的准确度。 逐一分析下上面的代码。代码前两行,做了几个导入操作,读入sklearn包。 导入随机森林分类器,导入将数据分成训练组合测试组模块。 模块train_test_split还会打乱数据的先后顺序。原有数据顺序可能含有误导实际预测的信息。 clf = RandomForestClassifier(max_depth=5,n_estimators=10)这句实现分类器,选择一个使用10个决策树 的森林,而每棵树最多允许五层的判断深度。这么设置避免过拟合。 接下来创建X矩阵和y向量。初始的iris数据框包含四个特征:花瓣宽度和长度,花萼的长度和宽度。 这些特征被选中并成为独立特征矩阵X。最后一列iris类别的名称,就成为因变量y。 """ from sklearn.ensemble import RandomForestClassifier from sklearn.model_selection import train_test_split # clf = RandomForestClassifier(max_depth=5,n_estimators=10) # X = df.ix[:,:4] # y = df.ix[:,4] """ X_train,X_test, y_train, y_test =cross_validation.train_test_split(train_data,train_target, test_size=0.4, random_state=0) train_data:所要划分的样本特征集 train_target:所要划分的样本结果 test_size:样本占比,如果是整数的话就是样本的数量 random_state:是随机数的种子。 随机数种子:其实就是该组随机数的编号,在需要重复试验的时候,保证得到一组一样的随机数。 比如你每次都填1,其他参数一样的情况下你得到的随机数组是一样的。但填0或不填,每次都会不一样。 """ # X_train,X_test,y_train,y_test = train_test_split(X,y,test_size=0.3) # clf.fit(X_train,y_train) # y_pred = clf.predict(X_test) # rf = pd.DataFrame(list(zip(y_pred,y_test)),columns=['predicted','actual']) # rf['correct'] = rf.apply(lambda r: 1 if r['predicted']==r['actual'] else 0 ,axis=1) # print(rf) # print(rf['correct'].sum()/rf['correct'].count()) #0.955555555556 """ 接下来使用训练数据拟合模型。一点模型训练完毕,再通过测试数据集来调用分类器的预测方法。 测试数据是分类器没有处理过的数据。预测的返回结果是预估标签的列表。 然后创建对应实际标签与预估标签的数据框。 最终,加和正确的预测次数,并除以样例的总数,从而看出预测的准确率。 """ #下面看看哪些特征提供最佳的辨别力。 # f_importances = clf.feature_importances_ # f_names = df.columns[:4] # f_std = np.std([tree.feature_importances_ for tree in clf.estimators_],axis=0) # zz = zip(f_importances,f_names,f_std) # zzs = sorted(zz,key=lambda s:x[0],reverse = True) # imps = [x[0] for x in zzs] # labels = [x[1] for x in zzs] # errs = [x[2] for x in zzs ] # plt.bar(range(len(f_importances)),imps,color='r',yerr=errs,align="center") # plt.xticks(range(len(f_importances)),labels) # plt.show() """ 由上图可以看出,花瓣的长度和宽度比较有区分力。 这些数字从哪里呢?随机森林有一个名为f_importances_的方法,返回特征在决策树中划分叶子结点的相对能力, 如果一个特征能够将分组一致性地、干净拆分成不同的类别,它就具有较高的特征重要性。 这个数字的总和将始终为1. """ #下面看看SVM分类器的结果 from sklearn.multiclass import OneVsRestClassifier from sklearn.svm import SVC from sklearn.model_selection import train_test_split clf=OneVsRestClassifier(SVC(kernel='linear')) X = df.ix[:,:4] y = np.array(df.ix[:,4]).astype(str) #SVM不能像随机森林分类器一样,交标签解释为N木偶用的字符串 X_train,X_test,y_train,y_test = train_test_split(X,y,test_size=0.3) clf.fit(X_train,y_train) y_pred=clf.predict(X_test) rf= pd.DataFrame(list(zip(y_pred,y_test)),columns=['predicted','actual']) rf['correct']=rf.apply(lambda r:1 if r['predicted']==r['actual'] else 0,axis=1) print(rf) print(rf['correct'].sum()/rf['correct'].count())
以上就是Python机器学习实践指南第一章的内容,介绍了数据科学/机器学习的工作流程。