Python机器学习实践指南 笔记(1)-Python机器学习的生态系统

来源:互联网 发布:简单的c语言程序题目 编辑:程序博客网 时间:2024/05/17 20:34

前言:我看的是英文原版第二版,看了这本书后,有这么一些感叹。
“原来许多看上去很难搞的机器学习,可以用简洁的python语言结合机器学习库搞定。而且机器学习的使用范围可以这么广。这本书就涉及到了在公寓、机票、IPO 市场、新闻源、内容推广、股票市场、图像、聊天机器人和推荐引擎等方面的应用,真的是五花八门。”
废话少说,下面是我做的笔记。

机器学习的工作流程包括六个步骤:获取,检查和探索,清理和准备,建模,评估和最后的部署。

一些python的示例
1.获取
让我们来看一个使用Requests进行交互的例子,它从GitHub的API中拉取数据。在这里,我们将对该API进行调用,并请求某个用户的starred库列表。starred表示用户对代码库感兴趣或者赞赏。

import requests r = requests.get(r"https://api.github.com/users/acombs/starred") r.json() 

2.检查和探索

2.1 Jupyter记事本
一个基于Web的前端(相对于IPython的内核而言)。
启动很简单,在安装了Anaconda 的python环境提示符下敲入 jupyter notebook
这里写图片描述
优点

以下列举了 Jupyter Notebook 的众多优点:
2.1.1 列表内容
极其适合数据分析
想象一下如下混乱的场景:你在终端中运行程序,可视化结果却显示在另一个窗口中,包含函数和类的脚本存在其他文档中,更可恶的是你还需另外写一份说明文档来解释程序如何执行以及结果如何。此时 Jupyter Notebook 从天而降,将所有内容收归一处,你是不是顿觉灵台清明,思路更加清晰了呢?

2.1.2 支持多语言
也许你习惯使用 R 语言来做数据分析,或者是想用学术界常用的 MATLAB 和 Mathematica,这些都不成问题,只要安装相对应的核(kernel)即可。这里列出了 Jupyter 支持的所有语言,供您参考。

2.1.3 分享便捷
支持以网页的形式分享,GitHub 中天然支持 Notebook 展示,也可以通过 nbviewer 分享你的文档。当然也支持导出成 HTML、Markdown 、PDF 等多种格式的文档。

2.14 远程运行
在任何地点都可以通过网络链接远程服务器来实现运算,这里给出一个远程运行的例子,可以体验一下 Jupyter Notebook。

2.1.5 交互式展现
不仅可以输出图片、视频、数学公式,甚至可以呈现一些互动的可视化内容,比如可以缩放的地图或者是可以旋转的三维模型。这就需要交互式插件(Interactive widgets)来支持。

2.2 Pandas
Pandas是一个卓越的数据分析库。
下面是使用例子

import os    import pandas as pd    import requests    PATH = r'/Users/alexcombs/Desktop/iris/' r= requests.get('https://archive.ics.uci.edu/ml/machine-learning-databases/iri s/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']) df.head() 

结果是
这里写图片描述
列名的意思是
花萼长度,花萼宽度,花瓣长度,花瓣宽度,类别
2.2.1 只看某一列

df['sepal length'] 

2.2.2 选择前两列和前四行

df.ix[:3, :2]

2.2.3 使用列表迭代器并只选择前四行描述width的列

df.ix[:3, [x for x in df.columns if 'width' in x]]  

2.2.4 列出所有可用的唯一类

df['class'].unique()

2.2.5 统计某一类别数量

df[df['class']=='Iris-virginica'].count() 

2.2.6 某类数据保存为一个新的数据框并重置索引序列号

virginica = df[df['class']=='Iris-virginica'].reset_index(drop=True)virginica

2.2.7 快速的描述性统计数据,包括数量,平均值,标准差,最大,最小,25%,50%,75%

df.describe()

自定义的百分比。

df.describe(percentiles=[.20,.40,.80,.90,.95])

2.2.8 特征之间是否有任何相关性

df.corr() 

通过传递方法的参数,还可以切换到Kendall’s tau或Spearman’s秩相关系数(例如

df.corr(method="spearman")

df.corr(method="kendall")

2.3 可视化
2.3.1 分别显示花萼长度,花萼宽度,花瓣长度,花瓣宽度直方图,观察数据分布情况

import matplotlib.pyplot as pltplt.style.use('ggplot')%matplotlib inline import numpy as npfig, 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()

这里写图片描述
2.3.2 散点图。这里我们将在x轴和y轴分布绘画点,每个点显示一个样本的花瓣宽度和花瓣长度。

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')

这里写图片描述
2.3.3 线图,显示所有样本的花瓣长度

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')

这里写图片描述
2.3.4 条形图,显示每个类别中每个特征的平均测量值

fig, ax = plt.subplots(figsize=(6,6)) bar_width = .8 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='white') 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'])

这里写图片描述
2.3.5 小提琴图,显示了特征在每个类别中的分布情况

#seaborn是专门为统计可视化而创建的库import seaborn as sns 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()

这里写图片描述
3.清理和准备
3.1.Map
假设我们觉得类别的名字太长了,并且希望使用特殊的3字母代码系统对其进行编码。为了实现这点,我们将使用map方法并将一个Python字典作为其参数。这里将为每个单独的花类型传入替换的文本。

df['class'] = df['class'].map({'Iris-setosa': 'SET', 'Iris-virginica': 'VIR', 'Iris-versicolor': 'VER'}) df

3.2 Apply
根据花瓣的宽度来创建新的列。之前我们看到花瓣宽度的平均值为1.3。现在,在数据框中创建一个新的列——宽花瓣,它包含一个基于petal width列的二进制值。如果花瓣宽度等于或宽于中值,那么我们将其编码为1,而如果它小于中值,我们将其编码为0。为了实现这点,这里将在petal width这列使用apply方法。

df['wide petal'] = df['petal width'].apply(lambda v: 1 if v >= 1.3 else 0) df 

新的特征列;花瓣的面积

df['petal area'] = df.apply(lambda r: r['petal length'] * r['petal width'], axis=1) df 

3.3 Applymap
数据框里所有的数据单元执行一个函数

df.applymap(lambda v: np.log(v) if isinstance(v, float) else v) 

3.4 Groupby
按照类别对数据进行了划分,并且提供了每个特征的均值

df.groupby('class').mean()

得到每个类别完全的描述性统计信息。

df.groupby('class').describe()

花瓣的宽度在不同类之间分布有一些比较明显的区别

df.groupby('petal width')['class'].unique().to_frame()

自定义的聚集函数。

df.groupby('class')['petal width']\ .agg({'delta': lambda x: x.max() - x.min(), 'max': np.max, 'min': np.min})

4.建模和评估

4.1 statsmodels
首先,通过散点图来目测花萼长度和花萼宽度两者的关系。

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)

这里写图片描述
似乎有一个正向的线性关系,也就是说,随着花萼宽度的增加,花萼长度也会增加。接下来我们使用statsmodels,在这个数据集上运行一个线性回归模型,来预估这种关系的强度。

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()) 

最终公式是Sepal Length = 2.6447 + 0.6909 × Sepal Width。我们也可以看到,该模型的R2值是一个可以接受的0.558,而p值 (Prob)是非常显著的4.75e-10<<0.05
这里写图片描述
现在让我们使用结果对象来绘制回归线。

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)

这里写图片描述
4.2 scikit-learn

scikit-learn是一个令人惊喜的Python库,作者们为其设计了无与伦比的文档,为几十个算法提供了统一的API接口。它建立在Python科学栈的核心模块之上,也就是NumPy、SciPy、pandas和matplotlib。scikit-learn覆盖的一些领域包括:分类、回归、聚类、降维、模型选择和预处理。

#第一个导入的是一个随机森林分类器,第二个导入的是一个将数据分成训练组和测试组的模块。from sklearn.ensemble import RandomForestClassifier from sklearn.cross_validation 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 = train_test_split(X, y, test_size=.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) rfrf['correct'].sum()/rf['correct'].count()

输出0.9555

让我们看看哪些特征提供了最佳的辨别力或者说预测能力。

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 x: 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); 

这里写图片描述
结果是花瓣的长度和宽度对于区分类别而言,具有更好的辨别力

切换分类器SVM

分类器并使用支持向量机(SVM)。

from sklearn.multiclass import OneVsRestClassifier from sklearn.svm import SVC from sklearn.cross_validation import train_test_split clf = OneVsRestClassifier(SVC(kernel='linear')) X = df.ix[:,:4] y = np.array(df.ix[:,4]).astype(str) X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=.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) rfrf['correct'].sum()/rf['correct'].count()

结果是0.9777

5.部署
将一个机器学习模型放入生产环境时,有许多可用的选项。它基本上取决于应用程序的性质。部署小到在本地机器上运行cron作业,大到在Amazon EC2实例上部署全面的实现。

原创粉丝点击