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

其他问题

升级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()  #画图

结果图

在这里插入图片描述

结果分析
  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()

结果图

在这里插入图片描述

结果分析
  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

在这里插入图片描述

  1. 使用线性svm

在这里插入图片描述

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

matplotlib.pyplot.imshow()方法

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值