机器学习从入门到创业手记-sklearn基础设计

       早上刚坐到座位上,看到刘思聪正在装扮自己的办公桌,桌台上有个他和女孩合影,他大方的递给我看说,告诉我是我这是她女朋友,在国家邮政工作,是他父亲朋友的女儿,我应付到好工作啊,挺稳定,他笑了笑,她家不指望她挣钱,就有个事情干就完了,我问那为什么选择去邮政工作啊?刘思聪笑的更开心了,说就因为离家近呀,走路几分钟就到了。原来炫富的方式真是多种多样呀,我知道那个附近的房价都在每平米8万以上。

      

       不羡慕别人的生活,因为那些都和你没有一点关系。我还是早点开始今天的工作吧,勤能补拙,但愿勤也能补穷。

 

      

PPT页1

      

       旁白:通常sklearn的自带数据库都有如下规则,采用字典结构存储,data关键字存放数组,每一行表示一个实例,每一列表示一个属性,target关键字存放目标数组,请加载mnist数据库,并显示其数据结构。

      

       安逸提交的代码:

 

from sklearn.datasets import fetch_mldata

mnist = fetch_mldata('MNIST original')

 

print ("MNIST data shape : ",mnist['data'].shape)

print ("MNIST target shape : ",mnist['target'].shape)

 

系统返回了输出结果:

 

MNIST data shape :  (70000, 784)

MNIST target shape :  (70000,)

 

旁白:MNIST有7000张图片,每张图片都是28x28像素的,为了压缩计算量我们将二维数据结构改为一维数据结构,故28 x 28 = 784 。

 

PPT页2

 

       旁白:PPT页2展示了MNIST手写数据样式,请尝试将data数据集中任选一数据还原成数字形式并显示出来。

 

       安逸提交的代码:

 

import matplotlib.pyplot as plt

#将索引为1234的数据还原,使用reshape函数来改变维数

digit_img = mnist['data'][1234].reshape(28,28)

plt.imshow(digit_img)

plt.axis("off")

plt.show()

 

系统返回图3.3.1

图3.3.1

 

旁白:您选出的数字为0,下面我们希望能在MNIST数据集中找到所有的数字0,将文字识别问题化为二分类问题,在分类算法中尝试用随机梯度下降算法,支持向量机算法与逻辑回归算法,请参考PPT页3提示完成对数字0的提取。

PPT页3

 

              我按照要求点击了随机梯度下降算法的链接,画面跳到PPT页4。

PPT页4

 

       旁白:随机梯度下降算法涉及到如下方面知识,如梯度下降,特征缩放,学习率的理解。

PPT页5

 

       旁白:PPT页5描述的是一个过程,想象在群山中想要找到山中的最低谷,你需要不断的往山下走去寻找,当找到一个下山路降趋势停止而改为上山路时,记录该谷底值为一个梯度下降的极值,这样你走遍群山终于找到了所有谷底值的最低值,这个过程被称为梯度下降,这里你每步走的距离被称为步长。梯度下降一般被用来求解最小损失函数。

PPT页6

      

       旁白:特征缩放针对的公式是Y = w1*X1 + w2 *X2等多特征属性的场景,若其中一个属性的取值范围过大,会导致其他取值范围小的属性变得对最终结果无关紧要,以公式为例,若X2取值范围是0~5000而X1的取值范围是0~1,则会发生最终的Y值只会受X2取值变化的影响。

 

PPT页7

      

旁白:假如你在山上利用梯度下降的方式去寻找谷底时,若你的学习速率过大,相当于步子迈的大下降的快,那么很有可能会在某一步就迈过了最低点,但如果你的学习速率过小,每次都只走1厘米,那样你要找到谷底则耗时过长,也就是收敛过慢,PPT页7中表示了在多轮迭代中,好的学习速率会让损失函数均匀而快速的收敛,过高的学习速率会造成无法收敛,过低的学习速率会在同样迭代轮数下完不成相应的收敛效果。

PPT页8

      

旁白:请根据PPT页8提供的随机梯度下降算法完成将手写数字中0调出的模型并提交代码。

 

安逸提交的代码:

 

from sklearn.model_selection import train_test_split

from sklearn.linear_model import SGDClassifier

 

X_train,X_test,y_train,y_test = train_test_split(mnist['data'],mnist['target'],random_state=33,test_size=0.25)

clf = SGDClassifier(loss="hinge", penalty="l2")

 

#二分类,等于0的为1,不等于0的为0

y_train_0 = (y_train == 0)

y_test_0 = (y_test == 0)

 

clf.fit(X_train,y_train_0)

sgd_y_pred = clf.predict(X_test)

print ('SGDClassifier is',clf.score(X_test,y_test_0))

 

 

系统输出:

 

SGDClassifier is 0.9870857142857142

 

旁白:SGDClassifier通过One VS Rest方式来组合二分类器,One VS Rest方式采用每一个分类都利用自身与其它所有剩余分类的特征区别并进行训练。可以实现多分类的判别。

 

PPT页9

      

PPT页10

      

       旁白:请结合PPT页9与PPT页10完成LinearSVC对手写数字的全分类,并统计成功率。

 

       安逸提交的代码:

 

from sklearn.datasets import fetch_mldata

mnist = fetch_mldata('MNIST original')

 

from sklearn.model_selection import train_test_split

from sklearn.pipeline import Pipeline

from sklearn.preprocessing import StandardScaler

from sklearn.svm import LinearSVC

 

X_train,X_test,y_train,y_test = train_test_split(mnist['data'],mnist['target'],random_state=33,test_size=0.25)

 

svm_clf = Pipeline([

       ("Scaler",StandardScaler()),("Linear_SVC",LinearSVC()),

       ])

svm_clf.fit(X_train,y_train)

y_pred = svm_clf.predict(X_test)

print("LinearSVC score : ",svm_clf.score(X_test,y_test))

 

系统输出:

 

LinearSVC score :  0.9030857142857143

 

       旁白:使用线性分类手写识别数据时,由于很多数据是重合在一起的单纯用线性很难分隔,我们需要使用核函数将低维数剧投射到高维数据中,使用超平面来进行空间的分隔,请参考PPT页11使用SVM的核函数再次验证。

 

PPT页11

 

       我按照PPT页12修改了再次提交代码,系统输出:

 

SVC score :  0.11142857142857143

 

PPT页12

 

       旁白:请根据PPT页12完成最邻近算法的设计。

      

       安逸提交的代码:

 

from sklearn.datasets import fetch_mldata

mnist = fetch_mldata('MNIST original')

 

from sklearn.model_selection import train_test_split

from sklearn.pipeline import Pipeline

from sklearn.preprocessing import StandardScaler

from sklearn.svm import LinearSVC

 

X_train,X_test,y_train,y_test = train_test_split(mnist['data'],mnist['target'],random_state=33,test_size=0.25)

 

from sklearn.neighbors import KNeighborsClassifier

 

knn_pipe =Pipeline([

                                   ("scaler",      StandardScaler()),

                                   ("knn_pipe",KNeighborsClassifier())

                            ])

 

knn_pipe.fit(X_train,y_train)

y_pred = knn_pipe.predict(X_test)

print("KNN score : ",knn_pipe.score(X_test,y_test))

 

系统输出:

 

KNN score :  0.9461142857142857

 

 

PPT页13

 

       旁白:使用score的接口可以得到模型总体的精确度,但却不直观,无法得知在每个目标分类的预测能力,所以sklearn提供了一个更加直观的接口用于显示全面的信息,精确率可以被理解为查准率,即预测出为正确的占样本的比例,而召回率是查全率,即在该目标分类中有多少被正确预测出的来,F1值为精确率与召回率的均值,请任选从之前练习中选择一个算法加入该模型性能报告。

 

       安逸提交的代码:

 

from sklearn.model_selection import train_test_split

from sklearn.linear_model import SGDClassifier

 

X_train,X_test,y_train,y_test = train_test_split(mnist['data'],mnist['target'],random_state=33,test_size=0.25)

clf = SGDClassifier(loss="hinge", penalty="l2")

 

clf.fit(X_train,y_train)

sgd_y_pred = clf.predict(X_test)

print ('SGDClassifier is',clf.score(X_test,y_test))

 

from sklearn import metrics

print(metrics.classification_report(y_test, sgd_y_pred))

 

系统输出如图3.3.1,左侧为0~9的10个手写数字分类,后面为对应每个分类的评估值,最后一行为平均统计值:

 

图3.3.1

 

PPT页14

 

旁白:如果想让模型有更好的效果需要设置对应的超参数,但就算最有经验的专家也无法通过抽象的数据就能确定这些复杂的参数,这里的解决办法是使用网格搜索来实现对模型中最佳超参数的搜寻工作,其原理是使用穷举方法将设定所有的参数都运行一遍,找到得分最好的超参数组合。请下载GridSearch.py文件运行根据输出并找到最佳参数。

 

下载并打开GridSearch.py

 

from sklearn import svm, datasets

from sklearn.model_selection import GridSearchCV

iris = datasets.load_iris()

parameters = {'kernel':('linear', 'rbf'), 'C':[1, 10]}

svc = svm.SVC()

clf = GridSearchCV(svc, parameters)

clf.fit(iris.data, iris.target)

print ("best_estimator_ : ",clf.best_estimator_)

print ("best_score_ : ",clf.best_score_)

print ("best_params_ : ",clf.best_params_)

 

 

图3.3.2

      

运行结果如图3.3.2,我从里面轻松找到了最佳超参集合和最佳分数,并提交给系统,系统也提示学习过关,我抬头环顾四周发现周围已经没什么同事了,系统托盘里显示已经21点多了。我赶快站起来往高维的位置看看,她基础那么差,是不是还没完成系统学习,令人意外的是,高维的座位上已经空空如也了。

 

晚上走在北京的街头,一丝丝凉意。

猜你喜欢

转载自blog.csdn.net/yoki2009/article/details/88547642