IDE为Jupyter Notebook
scikit-learn官网
scikit-learn是一个专门用于机器学习的工具包
运用到啥函数不知道咋使用?戳它–>scikit-learn工具包的API文档
不知道用啥模板?戳它–>scikit-learn样例模型
功能 | 翻译 |
---|---|
Classification | 分类 |
Regression | 回归 |
Clustering | 聚类 |
Dimensionality reduction | 降维算法 |
Model selection | 模型选择 |
Preprocessing | 数据预处理 |
一、首先导入相关的工具包,以及x轴y轴字体大小设置
import numpy as np
import os
%matplotlib inline
import matplotlib
import matplotlib.pyplot as plt
plt.rcParams['axes.labelsize'] = 14
plt.rcParams['xtick.labelsize'] = 12
plt.rcParams['ytick.labelsize'] = 12
import warnings
warnings.filterwarnings('ignore')
np.random.seed(42)
二、数据集读取
使用的数据集是sklearn内置数据集,MNIST
手写数字识别数据集,70000张灰度图像的数字,大小为(28,28,1),28 * 28 * 1=784,每一个图像样本都有784个像素点,可以的等价于784个特征。
免费MNIST手写数字识别数据集下载
将下载好的mnist-original放到C:\Users\MyPC\scikit_learn_data下创建一个mldata文件夹
#查看下路径
from sklearn.datasets.base import get_data_home
print (get_data_home())#C:\Users\MyPC\scikit_learn_data
from sklearn.datasets import fetch_openml
mnist = fetch_openml("mnist_784")#手写数字识别数据集,量少好观察
print(mnist)
#数据集中,X是mnist,里面存放类似字典的结构,里面所有数据的key是data;y是标签存放target
#X=mnist将data传入;y=mnist将target传入
X, y = mnist["data"], mnist["target"]
X.shape#(70000, 784) 当前样本数量一共7w个,784=28*28*1
y.shape#(70000,) 第一行标签为0,第二行标签为1,以此类推,共70000行
#前6w张当作训练集training,后1w张当作测试集testing
#1-6w 这6w个样本为训练集training、6w到最后7w 这1w个样本为testing测试集
X_train, X_test, y_train, y_test = X[:60000], X[60000:], y[:60000], y[60000:]
# 因为是数据之间是独立的,故需要洗牌操作,将training训练集和testing测试集打乱顺序
import numpy as npshuffle_index = np.random.permutation(60000)#打算数据集的index
X_train, y_train = X_train[shuffle_index], y_train[shuffle_index]#回传给数据集,相当于洗牌打乱操作
#原始index值为0,1,2,...,打乱顺序之后的index如下所示
shuffle_index#array([12628, 37730, 39991, ..., 860, 15795, 56422])
三、交叉验证
由上几步可得,将数据集的前6w为训练集training,后1w为测试集testing
首先:将整个数据集分为两部分训练集和测试集,其中测试集相当于高考,测试集是非常非常宝贵的东西,仅此一次。故为了效果更好,需要中途在进行几次模拟考试类似期中期末考试,这时候需要从训练集中再抽取出一部分充当期中期末考试,即验证集validation。
例如:training中有5份样本,交叉验证就是将这5份打乱,依次从中随机抽取1份为validation,剩下的为training。然后每次通过模型去训练,得出一个预测结果,求取平均值即可。
# 为了简单起见,这里只判断样本是否是5
y_train_5 = (y_train==5)#是否是5
y_test_5 = (y_test==5)#将10分类转换为2分类进行演示
#训练集前十个样本是不是5
y_train_5[:10]#array([False, False, False, False, False, False, False, False, False, True])
SGDClassifier的方法详细参数
#SGDClassifier 梯度下降分类器
from sklearn.linear_model import SGDClassifier
sgd_clf = SGDClassifier(max_iter=5,random_state=42)#max_iter最大迭代次数;random_state随机种子,每次随机策略都一样
sgd_clf.fit(X_train,y_train_5)#通过SGD训练分类器
'''
SGDClassifier(alpha=0.0001, average=False, class_weight=None,early_stopping=False, epsilon=0.1, eta0=0.0, fit_intercept=True,l1_ratio=0.15, learning_rate='optimal', loss='hinge', max_iter=5,n_iter=None, n_iter_no_change=5, n_jobs=None, penalty='l2',power_t=0.5, random_state=42, shuffle=True, tol=None,validation_fraction=0.1, verbose=0, warm_start=False)
'''
#训练完成之后,对该分类器进行测试,预测35000这个样本是5,为啥?然后进行通过索引查下是否是5
sgd_clf.predict([X[35000]])#array([ True])
#通过索引验证下35000样本是否是5
y[35000]#5.0
Ⅰ交叉验证的实现
cross_val_score方法的详细参数
"""
参数一:将训练的模型传入进来
参数二:传入当前的训练数据
参数三:当前的标签
参数四:cv=3表示把数据集切分成3分,最后进行3次交叉验证,会输出3个交叉验证的结果
参数五:使用什么指标进行评估得分,accuracy表示使用准确率来进行评估
"""
from sklearn.model_selection import cross_val_score
cross_val_score(sgd_clf,X_train,y_train_5,cv=3,scoring='accuracy')#array([0.9502 , 0.96565, 0.96495])
X_train.shape#(60000, 784)#训练的时候传入了6w个样本
y_train_5.shape#(60000,)
Ⅱ自己对数据集进行切分训练预测
StratifiedKFold方法的详细参数
clone方法的详细参数
因为把数据集切分为多份,每一份都需要用的和原来一样的分类器,相同的模型,相同的参数。
交叉验证为了保证公平,每次传入的参数都是相同的。为了保证公平,使用了clone方法。
from sklearn.model_selection import StratifiedKFold
from sklearn.base import cloneskflods = StratifiedKFold(n_splits=3,random_state=42)#将数据集分成3分,随机种子这里设置的为42
for train_index,test_index in skflods.split(X_train,y_train_5):#对每一份数据集进行fit操作,split方法,切分数据集和标签clone_clf = clone(sgd_clf)#克隆分类器X_train_folds = X_train[train_index]#通过索引找图片样本y_train_folds = y_train_5[train_index]#这三类训练和测试数据都要来源于trainingX_test_folds = X_train[test_index]y_test_folds = y_train_5[test_index]clone_clf.fit(X_train_folds,y_train_folds)y_pred = clone_clf.predict(X_test_folds)n_correct = sum(y_pred == y_test_folds)print(n_correct/len(y_pred))
"""
0.9502
0.96565
0.96495
"""
四、Confusion Matrix-混淆矩阵
已知条件:一个班100人,男80,女20。
目标:找出所有女生。
结果:从班里面找了50人,其中20个女的,30个男的。
相关Relevant,正类 | 无关NonRelevant,负类 | |
---|---|---|
被检索到Retrieved | True Positives,TP正类判定为正类,即准确判断出这是为女生 | False Positives,FP负类判定为正类,“存伪”,即分明是男生,却判断出是女生 |
没被检索到NotRetrieved | False Negatives,FN正类判定为负类,“去真”,即分明是女生,却判断出是男生 | True Negatives,TN负类判定为负类,即一个男生被判定是男生 |
故TP=20;FP=30;FN=0;TN=50
cross_val_predict方法的详细参数
"""
参数一:分类器的名称
参数二:训练集
参数三:标签
参数四:分成几份
"""
from sklearn.model_selection import cross_val_predict
y_train_pred = cross_val_predict(sgd_clf,X_train,y_train_5,cv=3)
y_train_pred.shape#(60000,)#训练的时候传入了6w个样本,得到6w个样本的预测结果
X_train.shape#(60000, 784)
confusion_matrix方法的详细参数
"""
一般的混淆矩阵参数为2×2
参数一:训练值
参数二:实际预测结果
"""
from sklearn.metrics import confusion_matrix
confusion_matrix(y_train_5,y_train_pred)
"""
array([[53272, 1307],[ 1077, 4344]], dtype=int64)
"""
对于array数组中参数分析:
五、Precision精度 and Recall召回率
Positives:==5
Negatives: ≠5
precision_score方法的详细参数
recall_score方法的详细参数
from sklearn.metrics import precision_score,recall_score
precision_score(y_train_5,y_train_pred)#0.7687135020350381
recall_score(y_train_5,y_train_pred)#0.801328168234643
将Precision 和 Recall结合到一个称为F1 score 的指标,调和平均值给予低值更多权重。 因此,如果召回和精确度都很高,分类器将获得高F 1分数。
f1_score方法的详细参数
from sklearn.metrics import f1_score
f1_score(y_train_5,y_train_pred)#0.7846820809248555
六、阈值对结果的影响
decision_function方法的详细参数
y_scores = sgd_clf.decision_function([X[35000]])
y_scores#array([43349.73739616])
t = 50000
y_pred = (y_scores > t)#设置阈值
y_pred#array([False])
Scikit-Learn不允许直接设置阈值,但它可以得到决策分数,调用其decision_function()方法,而不是调用分类器的predict()方法,该方法返回每个实例的分数,然后使用想要的阈值根据这些分数进行预测:
y_scores = cross_val_predict(sgd_clf, X_train, y_train_5, cv=3, method="decision_function")
y_scores[:10]
"""
array([ -434076.49813641, -1825667.15281624, -767086.76186905,-482514.55006702, -466416.8082872 , -311904.74603814,-582112.5580173 , -180811.15850786, -442648.13282116,-87710.09830358])
"""
from sklearn.metrics import precision_recall_curve
precisions, recalls, thresholds = precision_recall_curve(y_train_5, y_scores)
y_train_5.shape#(60000,)#6w个样本
thresholds.shape#(59698,)#59698个阈值
precisions[:10]
"""
array([0.09080706, 0.09079183, 0.09079335, 0.09079487, 0.09079639,0.09079792, 0.09079944, 0.09080096, 0.09080248, 0.090804 ])
"""
precisions.shape#(59699,)#59699个阈值
recalls.shape#(59699,)#59699个阈值
对于不同的阈值,随着阈值的变换,精度和召回率变换的情况如下:
def plot_precision_recall_vs_threshold(precisions,recalls,thresholds):plt.plot(thresholds,precisions[:-1],"b--",label="Precision")plt.plot(thresholds,recalls[:-1],"g-",label="Recall")plt.xlabel("Threshold",fontsize=16)plt.legend(loc="upper left",fontsize=16)plt.ylim([0,1])plt.figure(figsize=(8, 4))
plot_precision_recall_vs_threshold(precisions,recalls,thresholds)
plt.xlim([-700000, 700000])
plt.show()
随着Recall的变换,Precision的变换如下:
def plot_precision_vs_recall(precisions, recalls):plt.plot(recalls, precisions, "b-", linewidth=2)plt.xlabel("Recall", fontsize=16)plt.ylabel("Precision", fontsize=16)plt.axis([0, 1, 0, 1])plt.figure(figsize=(8, 6))
plot_precision_vs_recall(precisions, recalls)
plt.show()
七、ROC curves(常用)
receiver operating characteristic (ROC) 曲线是二元分类中的常用评估方法
①它与精确度/召回曲线非常相似,但ROC曲线不是绘制精确度与召回率,而是绘制true positive rate(TPR) 与false positive rate(FPR)
②要绘制ROC曲线,首先需要使用roc_curve()函数计算各种阈值的TPR和FPR:
TPR = TP / (TP + FN) (Recall)
FPR = FP / (FP + TN)
from sklearn.metrics import roc_curve
fpr, tpr, thresholds = roc_curve(y_train_5, y_scores)
def plot_roc_curve(fpr, tpr, label=None):plt.plot(fpr, tpr, linewidth=2, label=label)plt.plot([0, 1], [0, 1], 'k--')plt.axis([0, 1, 0, 1])plt.xlabel('False Positive Rate', fontsize=16)plt.ylabel('True Positive Rate', fontsize=16)plt.figure(figsize=(8, 6))
plot_roc_curve(fpr, tpr)
plt.show()
虚线表示纯随机分类器的ROC曲线; 一个好的分类器尽可能远离该线(朝左上角)。
比较分类器的一种方法是测量曲线下面积(AUC)。完美分类器的ROC AUC等于1,而纯随机分类器的ROC AUC等于0.5。 Scikit-Learn提供了计算ROC AUC的函数:
from sklearn.metrics import roc_auc_scoreroc_auc_score(y_train_5, y_scores)#0.9624496555967156