欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

机器学习sklearn实战笔记(三)

程序员文章站 2022-04-07 17:20:51
...

其他问题

升级sklearn到最新版本

conda install scikit-learn=0.21

升级matplotlib到最新版本

conda install matplotlib=3.1.0

支持向量机(SVM)

支持向量机实现简单二分类任务并绘图
详细
  1. 二分类任务
  2. 样本数:40,特征数,2
  3. 无核函数
  4. 正负样本平衡
目标
  1. 对样本数据进行分类并绘图
详细代码
# 支持向量机的例子
from sklearn.model_selection import train_test_split

import numpy as np
import matplotlib.pyplot as plt
from sklearn import svm
from sklearn.datasets import make_blobs

# 使用make_blobs创建了40个点
# 默认是两个特征 
# n_samples:样本数量, 
# centers 创建的中心数(几类), 
# random_state 指定一个数,保证每次生成的数据相同
# cluster_std 两类样本的方差,调整方差使点更加松散 
X, y = make_blobs(n_samples=40, centers=2, random_state=6, cluster_std=[1.0, 2.0])

#  C是惩罚系数,即对误差的宽容度。c越高,说明越不能容忍出现误差,容易过拟合
#  C越小,容易欠拟合。C过大或过小,泛化能力变差
#  kernel 这里选择的是线性核,即是最简单的线性svm
clf = svm.SVC(kernel='linear', C=1000)

#分割成训练集和测试集, test_size是比例 ,指定random_state会使每次分割的数据集相同
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=14)
#进行模型训练
clf.fit(X_train, y_train)
#模型预测
clf.predict(X_test)
#打印预测的分数
_score = clf.score(X_test, y_test)
print(_score) #0.8333333333333334


# 画点
# 测试集: 横坐标, 纵坐标, c=y_train y_train的值不同,点的颜色也不同, cmap指定一种颜色分布规律
plt.scatter(X_train[:, 0], X_train[:, 1], c=y_train, s=30, cmap=plt.cm.Paired)
# 训练集: 横坐标, 纵坐标, marker 代表训练集的点使用x来表示,默认是o
plt.scatter(X_test[:, 0], X_test[:, 1], c=y_test, s=30, cmap=plt.cm.Paired, marker="x")

#接下来是画svm的超平面
ax = plt.gca()

xlim = ax.get_xlim()  # 获得x轴最大最小值
# print(xlim) (3.976374301845057, 10.80436834848946)
ylim = ax.get_ylim()  # 获得y轴最大最小值
# print(ylim) (-11.076622589861897, -1.0862982622797808)

#将x轴,y轴分别分成30份
xx = np.linspace(xlim[0], xlim[1], 30)  
yy = np.linspace(ylim[0], ylim[1], 30)

# 接受两个一维数组生成两个二维矩阵,
# XX (30, 30)
# YY (30, 30)
YY, XX = np.meshgrid(yy, xx)


# 拉平XX矩阵, 拉平YY矩阵, 并将矩阵竖着拼接
# print(XX.ravel())
# print("---------")
# print(YY.ravel())
# print("---------")
# print(np.vstack([XX.ravel(), YY.ravel()]))
# print("---------")
# print(np.vstack([XX.ravel(), YY.ravel()]).T) # 进行行列转换
# print("---------")
xy = np.vstack([XX.ravel(), YY.ravel()]).T  # shape(900,2)  xy即每对 (x,y)点坐标

# decision_function 计算出每队(x,y)点到超平面的函数间隔,并使用reshape还原成之前点的矩阵形式
# 求出了每个点的z值,z即是超平面的函数间隔
Z = clf.decision_function(xy).reshape(XX.shape)

# 画出决策边界
ax.contour(XX, YY, Z, colors='k', levels=[-1, 0, 1], alpha=0.5,
           linestyles=['--', '-', '--'])  # alpha表示透明度 cmap渐变标准

# 支持向量上划圈
# clf.support_vectors_  获得支持向量
# s是圆圈的大小 linewidth是线的粗细 facecolors是颜色填充 edgecolors 边界的颜色
ax.scatter(clf.support_vectors_[:, 0], clf.support_vectors_[:, 1], s=500,
           linewidth=1, facecolors='none', edgecolors='k')
plt.show()  #画图

结果图

机器学习sklearn实战笔记(三)

结果分析
  1. 圈起来的是支持向量
  2. 不同颜色代表不同样本
  3. 虚线代表决策边界
  4. x代表测试集,o代表训练集
  5. 分割正确的样本会出现在正确的位置,否则会落在边界或者是错误的位置
附录

make_blobs模块的使用

linspace(a,b,10) 生成从a到b 10个数的等差数列

meshgrid 将两个向量合并成一个矩阵

ravel 矩阵拉成一行

vstack 矩阵列合并

.T 矩阵转置

具有单变量特征选择的SVM
详细
目标
  1. 测试不同特征选择率下的数据拟合效果并绘图
详细代码
# 具有单变量特征选择的SVM
#  https://scikit-learn.org/stable/auto_examples/svm/plot_svm_anova.html#sphx-glr-auto-examples-svm-plot-svm-anova-py
#  SVM-Anova: SVM with univariate feature selection

import numpy as np
import matplotlib.pyplot as plt
from sklearn.datasets import load_iris
from sklearn.feature_selection import SelectPercentile, chi2
from sklearn.model_selection import cross_val_score
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import StandardScaler
from sklearn.svm import SVC

# #############################################################################
# return_X_y控制输出数据的结构,若选为True,则将因变量和自变量独立导出;
# 即X 对应data y对应target
X, y = load_iris(return_X_y=True)  # 导入数据
# print(X.shape)  # (150, 4)
# 设置随机数种子,保证每次随机到的数据相同
np.random.seed(0)
x_shape_ = 2 * np.random.random((X.shape[0], 36))  # 生成一个随机数矩阵
# print(x_shape_.shape)  # (150, 36)
X = np.hstack((X, x_shape_))
# print(X.shape)  # (150, 40) 

# #############################################################################
# Pipeline, 数据按照给定的参数顺序进行处理,按顺序执行列表中的 ----transform---方法

# 特征选择: 就是看自变量对因变量的相关性
# SelectPercentile 选择排名排在前n%的变量  默认percentile=10  即选择前10%最相关的特征,选择方法:卡方检验(chi2)
# chi2 卡方检验

# preprocessing.scale 是归一化方法,数据会缩到(0,1)范围
# StandardScaler 另一种特征缩放方法,但不会缩到(0,1)范围 但对异常点不敏感
clf = Pipeline([('anova', SelectPercentile(chi2)),
                ('scaler', StandardScaler()),
                ('svc', SVC(gamma="auto"))])

# #############################################################################
# 创建用于绘图的数据
score_means = list()   # mean平均数
score_stds = list()  # std标准差
percentiles = (1, 3, 6, 10, 15, 20, 30, 40, 60, 80, 100)

# anova 方差分析
# 用于确定特征选择的百分比的不同水平对结果的影响程度如何
for percentile in percentiles:
    # anova__percentile 改变前面别名anova的percentile参数的 也就是设置		SelectPercentile.percentile属性,即:改变特征选择的百分比
    clf.set_params(anova__percentile=percentile)
    # 最简单的交叉验证方法,cv选择折数,默认是3折交叉验证 这里是 5折交叉验证
    this_scores = cross_val_score(clf, X, y, cv=5)
    score_means.append(this_scores.mean()) 
    score_stds.append(this_scores.std())  

# errorbar  绘制误差条,即图片上的一堆竖线  
# 横坐标百分比, 纵坐标是平均值 , 误差是 np.array(score_stds)
plt.errorbar(percentiles, score_means, yerr=np.array(score_stds))
# plt.errorbar(percentiles, score_means, np.array(score_stds))   以上两个代码等效

# 所选特征的百分比的改变所引起的SVM方差分析的性能改变程度
plt.title(
    'Performance of the SVM-Anova varying the percentile of features selected')
plt.xticks(np.linspace(0, 100, 11, endpoint=True))  # 设置横坐标刻度
plt.xlabel('Percentile')
plt.ylabel('Accuracy Score')
plt.axis('tight')
plt.show()

结果图

机器学习sklearn实战笔记(三)

结果分析
  1. 在此例中,特征选择率是10%时,准确率最高
  2. 竖线是误差条
附录
  1. pipeline
    • Pipeline构造器接受(name, transform) tuple的列表作为参数。按顺序执行列表中的 ----transform----,完成数据预处理
    • 除了最后一个tansform,其余的transform必须实现fit_transform函数
    • 上一个transform类中fit_transform函数的返回值作为下一个transform类fit_transform函数的参数,所以在自己实现自定义的transform类的时候必须要实现fit_transform函数
    • fit_transform 返回值为 numpy array
  2. SelectPercentile/SelectKBest 特征选择,选择排名靠前特征作为新特征
    • SelectPercentile 选择排名排在前n%的变量 默认percentile=10 即选择前10%最相关的特征,
    • 特征选择方法:卡方检验(chi2)
    • SelectKBest选择排名排在前n个的变量
  3. StandardScaler 特征缩放
    • 一种特征缩放方法,但不会缩到(0,1),对异常点不敏感
    • StandardScaler 使用该类的好处在于可以保存训练集中的参数(均值、方差)直接使用其对象转换测试集数据。
    • preprocessing.scale 是另一种特征缩放方法,又称归一化方法,数据会缩到(0,1)范围
非线性svm
详细
  1. 二分类任务
  2. 样本数300
  3. 非线性svm, 高斯核(rbf)
  4. 正负样本均衡
目标
  1. 对样本数据进行分类并绘图
详细代码
#  非线性SVM
#  Non-linear SVM
#  https://scikit-learn.org/stable/auto_examples/svm/plot_svm_nonlinear.html#sphx-glr-auto-examples-svm-plot-svm-nonlinear-py

import numpy as np
import matplotlib.pyplot as plt
from sklearn import svm

# 模拟数据
from sklearn.model_selection import train_test_split

xx, yy = np.meshgrid(np.linspace(-3, 3, 500),
                     np.linspace(-3, 3, 500))
np.random.seed(0)
X = np.random.randn(300, 2)  # randn函数返回一个或一组样本,具有标准正态分布  shape(300,2)
# 为样本添加标签
# 逻辑或操作,如果第一个特征和第二个特征均大于0则为true,否则为false,(true,和false这里作为标签)
Y = np.logical_xor(X[:, 0] > 0, X[:, 1] > 0)  # shape(300,) 1行300个 bool数组

X_train, X_test, y_train, y_test = train_test_split(X, Y, test_size=0.3, random_state=14)

# fit the model
# 采用 rbf内核 Radial Based Function 指的是我们要计算的函数的结果只和距离(∥x−xn∥)有关;
# rbf内核可以进行非线性分类
# 与SVC类似,但使用一个参数来控制支持向量的数量
clf = svm.NuSVC(gamma='auto')
# clf = svm.LinearSVC()  如果是linear内核就只能是线性的   polynomial内核  (多项式内核)也是非线性的
# clf = svm.SVC()
clf.fit(X_train, y_train)
y_res = clf.predict(X_test)
_score = clf.score(X_test, y_test)
print(_score)

# np.r_是按列连接两个矩阵,就是把两矩阵上下相加,要求列数相等。  添加行
# np.c_是按行连接两个矩阵,就是把两矩阵左右相加,要求行数相等。  添加列
Z = clf.decision_function(np.c_[xx.ravel(), yy.ravel()])
Z = Z.reshape(xx.shape)

# 绘制热图
# Z 类数组对象(array_like),shape(n,m) 或者(n,m,3)或者(n,m,4) 分别对应颜色表示方式
# 热图(heatmap)是数据分析的常用方法,通过色差、亮度来展示数据的差异、易于理解
# interpolation代表的是插值运算,'nearest'只是选取了其中的一种插值方式 用于图片缩放
# aspect='auto' 则改变图片的横纵比、以便适应坐标轴的横纵比
# extent 图表的X、Y轴的刻度标签所指定的范围. 即让指定了图像四个角的坐标
# 使用origin =’upper’,数组Z的[0,0]索引位于范围的左上角.如果origin =’lower’,它将被放置在左下角.
plt.imshow(Z, interpolation='nearest',
           extent=(xx.min(), xx.max(), yy.min(), yy.max()), aspect='auto',
           origin='upper', cmap=plt.cm.PuOr_r)
contours = plt.contour(xx, yy, Z, levels=[0], linewidths=2,
                       linestyles='dashed')
plt.scatter(X_train[:, 0], X_train[:, 1], s=30, c=y_train, cmap=plt.cm.Paired,
            edgecolors='k')
plt.scatter(X_test[:, 0], X_test[:, 1], s=30, c=y_test,
            edgecolors='k', marker="x", cmap=plt.cm.Paired)
# 设置横纵坐标,因为没有参数,相当于取消横纵坐标
plt.xticks(())
plt.yticks(())
plt.axis([-3, 3, -3, 3])
plt.show()

结果图
  1. 使用非线性svm

机器学习sklearn实战笔记(三)

  1. 使用线性svm

机器学习sklearn实战笔记(三)

结果分析
  1. 使用非线性的svm在此例中效果明显更好
附录

matplotlib.pyplot.imshow()方法

在matplotlib中缩放图像而不更改轴

相关标签: 教程