数据分析(十二)

支持向量机SVM(Support Vector Machine)

【关键字】支持向量,最大几何间距

一、支持向量机的原理

Support Vector Machine 支持向量机,其含义是通过支持向量运算的分类器。其中“机”的意思是机器,可以理解为分类器。那么什么是支持向量呢?在求解的过程中,会发现只根据部分数据就可以确定分类器,这些数据称为支持向量。在一个二维环境中,其中点R,S,G点和其他靠近中间黑线的点可以看作为支持向量,他们可以决定分类器,也就是黑线的具体参数

(http://localhost:8888/notebooks/数据分析/day12/12_svm_kmeans/code/img1/1.png)

二、实战

1、画出决策边界

导包:sklearn.svm

随机生成数据,并且进行训练

导入三剑客

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt

导入支持向量机的分类的算法

SVC用于分类 SVR用于回归

from sklearn.svm import SVC

自己捏造一些玩具数据

为了展示效果好一些,我这里先加一个随机数的种子(大家自己写的时候就不要用种子了)

np.random.seed(0)
np.random.randn(20,2)  #20个点 每个点(样本)有x和y
dots1 = np.random.randn(20,2)-[1,4]
dots2 = np.random.randn(20,2)+[2,3]
X_train = np.concatenate((dots1,dots2))  # 训练集的特征值
# 产生了 两组 点 中心 分别是 -1,-4 和 2,3
# 前20个是0 后20个是1
y_train = [0]*20+[1]*20  # 给两组分类的样本 添加目标值
X_train = np.random.randn(20,2)-[1,4]
plt.scatter(X_train[:,0],X_train[:,1],c=y_train)
# svm也是分析各个特征的权重
svc = SVC(kernel='linear')  # 这里我们先用线性的看效果
svc.fit(X_train,y_train)
svc.coef_  # 支持向量机 也是 得到各个特征的权重 (是两个特征针对于 分类结果的权重)
svc.intercept_  # 截距

已知x/z 和 y/z 求 y相对于x的斜率

绘制三维图形 把x对于z 以及 y对于z的斜率绘制出来

from mpl_toolkits.mplot3d.axes3d import Axes3D
# 按照原来x的范围 去产生一系列x
x = np.linspace(0,4,100)
y = np.linspace(0,4,100)
svc.intercept_[0]
svc.coef_[0,1]
# 已知x对于z的斜率 y对于z的斜率 绘制 y=w*x+b
# z=w1*x+w2*y+b
# z = svc.coef_[0,0]*x+svc.coef_[0,1]*y+svc.intercept_[0]
fig = plt.figure()
axes = Axes3D(fig)
# xs, ys, zs=0
axes.scatter(X_train[:,0],X_train[:,1])
# 把 z = svc.coef_[0,0]*x+svc.coef_[0,1]*y+svc.intercept_[0] 这条线 在三维坐标系中绘制出来
axes.plot(x,y,svc.coef_[0,0]*x+svc.coef_[0,1]*y+svc.intercept_[0])

# 求 直线 在 z=0的平面上的 投影线的 斜率
# 0 = svc.coef_[0,0]*x+svc.coef_[0,1]*y+svc.intercept_[0]
# y = w*x+b
# svc.coef_[0,1]*y=-svc.coef_[0,0]*x-svc.intercept_[0]
# svc.coef_[0,0]是x和z的
# svc.coef_[0,1]是y和z的
# x/y = (x/z)/(y/z)
# y=(-svc.coef_[0,0]/svc.coef_[0,1])*x+(-svc.intercept_[0]/svc.coef_[0,1])

x = np.linspace(-3,4,100)
#绘制出分割线
plt.scatter(X_train[:,0],X_train[:,1],c=y_train)
y = (-svc.coef_[0,0]/svc.coef_[0,1])*x+(-svc.intercept_[0]/svc.coef_[0,1])
plt.plot(x,y)
#使用svc.support_vectors_找出支持向量,即离分割线最近的点集合,绘制出支持向量的所有点
# 获取支持向量
svecs = svc.support_vectors_
svecs
# 绘制原有的 所有样本
plt.scatter(X_train[:,0],X_train[:,1],c=y_train)
# 绘制支持向量 (把支持向量的点 绘制的大一点)
plt.scatter(svecs[:,0],svecs[:,1],s=200,alpha=0.2,c='r')
# 计算和绘制 分类边界线
y = (-svc.coef_[0,0]/svc.coef_[0,1])*x+(-svc.intercept_[0]/svc.coef_[0,1])
plt.plot(x,y)
#绘制两条线,分别经过支持向量的第一个点和最后一个点,即查看分割线两边的通过支持向量的平行线
#绘制图形
w = -svc.coef_[0,0]/svc.coef_[0,1]
w
svecs[0]
x1 = svecs[0,0]
x1
y1 = svecs[0,1]
y1
# 过第一个支持向量 绘制曲线
# 已知斜率 和 要经过的 一个点 求解 y=w*x+b这个方程
# y=w*x+b
# y1=w*x1+b1
b1 = y1-w*x1
b1
# 绘制原有的 所有样本
plt.scatter(X_train[:,0],X_train[:,1],c=y_train)
# 绘制支持向量 (把支持向量的点 绘制的大一点)
plt.scatter(svecs[:,0],svecs[:,1],s=200,alpha=0.2,c='r')
# 计算和绘制 分类边界线
y = (-svc.coef_[0,0]/svc.coef_[0,1])*x+(-svc.intercept_[0]/svc.coef_[0,1])
plt.plot(x,y)
# 绘制 下边界
y2 = (-svc.coef_[0,0]/svc.coef_[0,1])*x+b1
plt.plot(x,y2,ls='--')  # 下面的边界
svecs  # x2,y2就是支持向量中的最后那个点的座标
x2 = svecs[2,0]  # 横坐标
x2
y2 = svecs[2,1]  # 纵坐标
y2
w
# 已知 过 一点 和 斜率 求解方程 y=w*x+b
# y2 = w*x2+b2
b2 = y2-w*x2
b2
# 绘制原有的 所有样本
plt.scatter(X_train[:,0],X_train[:,1],c=y_train)
# 绘制支持向量 (把支持向量的点 绘制的大一点)
plt.scatter(svecs[:,0],svecs[:,1],s=200,alpha=0.2,c='r')
# 计算和绘制 分类边界线
y = (-svc.coef_[0,0]/svc.coef_[0,1])*x+(-svc.intercept_[0]/svc.coef_[0,1])
plt.plot(x,y)
# 绘制 下边界
y2 = (-svc.coef_[0,0]/svc.coef_[0,1])*x+b1
plt.plot(x,y2,ls='--')  # 下面的边界
# 绘制 上边界
y3 = (-svc.coef_[0,0]/svc.coef_[0,1])*x+b2
plt.plot(x,y3,ls='--')

2、使用多种核函数对iris数据集进行分类

导包: from sklearn.datasets import load_iris

from sklearn.datasets import load_iris
iris = load_iris()
data = iris.data  # 特征值
target = iris.target # 目标值

提取数据只提取两个特征,方便画图

创建支持向量机的模型:‘linear’, ‘poly’(多项式), ‘rbf’(Radial Basis Function:基于半径函数),

X_train = data[:,:2]
y_train = target
plt.scatter(X_train[:,0],X_train[:,1],c=y_train)
# 获取模型
linear = SVC(kernel='linear')  # 线性内核 y=w*x+b
rbf = SVC(kernel='rbf')  # 基于半径的函数 其实就是二次函数
poly = SVC(kernel='poly')  # 更高次的函数  (一般不用)

训练模型

linear.fit(X_train,y_train)
rbf.fit(X_train,y_train)
poly.fit(X_train,y_train)  # 这个只是警告 告诉大家 某些参数在0.22版本中 会有调整

图片背景点

# 产生 能够 铺满 整个 画布的 点 作为测试集
# X_test
xmin,xmax = X_train[:,0].min(),X_train[:,0].max()
ymin,ymax = X_train[:,1].min(),X_train[:,1].max()
x = np.linspace(xmin-4,xmax+4,100)
y = np.linspace(ymin-2,ymax+2,100)
xx,yy = np.meshgrid(x,y)
X_test = np.c_[xx.flatten(),yy.flatten()]
plt.scatter(X_test[:,0],X_test[:,1])
# 使用测试集 进行 预测
y1_ = linear.predict(X_test)
y2_ = rbf.predict(X_test)
y3_ = poly.predict(X_test)

预测并绘制图形

from matplotlib.colors import ListedColormap
cm1 = ListedColormap(['r','g','b'])
plt.scatter(X_test[:,0],X_test[:,1],c=y1_)  # 线性的
plt.scatter(X_train[:,0],X_train[:,1],c=y_train,cmap=cm1)

plt.scatter(X_test[:,0],X_test[:,1],c=y2_)  # rbf 用来分类的函数是曲线(等一会 把 范围扩大系 效果更明显)
plt.scatter(X_train[:,0],X_train[:,1],c=y_train,cmap=cm1)

plt.scatter(X_test[:,0],X_test[:,1],c=y3_)  # 更高次的曲线
plt.scatter(X_train[:,0],X_train[:,1],c=y_train,cmap=cm1)

3、使用SVM多种核函数进行回归

#导包
from sklearn.svm import SVR  # 处理回归问题用SVR
#自定义样本点rand,并且生成sin函数曲线
# -pi pi 产生40个x
x = np.linspace(-np.pi,np.pi,40)
x
y = np.sin(x)
plt.scatter(x,y)

数据加噪

# 产生8个噪音 每隔5个点 添加一个噪声
# np.random.random(8)  # 0-1之间的随机数
noise = np.random.random(8) - 0.5  # -0.5 0.5之间的随机数
noise
y[::5]+=noise
plt.scatter(x,y)

建立模型,训练数据,并预测数据,预测训练数据就行

# 使用三种 不同的内核 做 回归
linear = SVR(kernel='linear')  # 一次曲线
rbf = SVR(kernel='rbf')  # 二次曲线
poly = SVR(kernel='poly')  # 高次曲线
linear.fit(x.reshape(-1,1),y)
rbf.fit(x.reshape(-1,1),y)
poly.fit(x.reshape(-1,1),y)
# 产生测试数据
X_test = np.linspace(-np.pi,np.pi,15).reshape(-1,1)
X_test
y1_ = linear.predict(X_test)
y2_ = rbf.predict(X_test)
y3_ = poly.predict(X_test)

绘制图形,观察三种支持向量机内核不同

plt.scatter(x,y,c='k',label='real')
# svm回归 使用linear内核
plt.plot(X_test,y1_,c='r',label='linear')
# svm回归 使用rbf内核
plt.plot(X_test,y2_,c='g',label='rbf')  # rbf即可以绘制曲线 也可以绘制直线 预测结果如果不是高次的对应关系预测出来的结果都比较准
# svm回归 使用poly内核
plt.plot(X_test,y3_,c='b',label='poly')  # 虽然能绘制曲线 但是很难预测准确
plt.legend()

K均值算法(K-means)聚类

【关键词】K个种子,均值

一、K-means算法原理

聚类的概念:一种无监督的学习,事先不知道类别,自动将相似的对象归到同一个簇中。

K-Means算法是一种聚类分析(cluster analysis)的算法,其主要是来计算数据聚集的算法,主要通过不断地取离种子点最近均值的算法。

K-Means算法主要解决的问题如下图所示。我们可以看到,在图的左边有一些点,我们用肉眼可以看出来有四个点群,但是我们怎么通过计算机程序找出这几个点群来呢?于是就出现了我们的K-Means算法

K-Means的算法如下:

  1. 随机在图中取K(这里K=2)个种子点。
  2. 然后对图中的所有点求到这K个种子点的距离,假如点Pi离种子点Si最近,那么Pi属于Si点群。(上图中,我们可以看到A,B属于上面的种子点,C,D,E属于下面中部的种子点)
  3. 接下来,我们要移动种子点到属于他的“点群”的中心。(见图上的第三步)
  4. 然后重复第2)和第3)步,直到,种子点没有移动(我们可以看到图中的第四步上面的种子点聚合了A,B,C,下面的种子点聚合了D,E)。

这个算法很简单,重点说一下“求点群中心的算法”:欧氏距离(Euclidean Distance):差的平方和的平方根

K-Means主要最重大的缺陷——都和初始值有关:

K是事先给定的,这个K值的选定是非常难以估计的。很多时候,事先并不知道给定的数据集应该分成多少个类别才最合适。(ISODATA算法通过类的自动合并和分裂,得到较为合理的类型数目K)

K-Means算法需要用初始随机种子点来搞,这个随机种子点太重要,不同的随机种子点会有得到完全不同的结果。(K-Means++算法可以用来解决这个问题,其可以有效地选择初始点)

总结:K-Means算法步骤:

  1. 从数据中选择k个对象作为初始聚类中心;
  2. 计算每个聚类对象到聚类中心的距离来划分;
  3. 再次计算每个聚类中心
  4. 计算标准测度函数,直到达到最大迭代次数,则停止,否则,继续操作。
  5. 确定最优的聚类中心

K-Means算法应用

看到这里,你会说,K-Means算法看来很简单,而且好像就是在玩坐标点,没什么真实用处。而且,这个算法缺陷很多,还不如人工呢。是的,前面的例子只是玩二维坐标点,的确没什么意思。但是你想一下下面的几个问题:

1)如果不是二维的,是多维的,如5维的,那么,就只能用计算机来计算了。

2)二维坐标点的X,Y 坐标,其实是一种向量,是一种数学抽象。现实世界中很多属性是可以抽象成向量的,比如,我们的年龄,我们的喜好,我们的商品,等等,能抽象成向量的目的就是可以让计算机知道某两个属性间的距离。如:我们认为,18岁的人离24岁的人的距离要比离12岁的距离要近,鞋子这个商品离衣服这个商品的距离要比电脑要近,等等。

二、实战

重要参数:

  • n_clusters:聚类的个数

重要属性:

  • cluster_centers_ : [n_clusters, n_features]的数组,表示聚类中心点的坐标

  • labels_ : 每个样本点的标签

    import numpy as np
    import pandas as pd
    import matplotlib.pyplot as plt

1、聚类实例

导包,使用make_blobs生成随机点cluster_std

from sklearn import datasets
# datasets里面有好多数据集 datasets就是用来提供数据的
# load 开头的 都是从本地加载的数据
# fetch 开头的 都是从网上下载的数据
# make 开头的 都是按照指定的参数 去创建一些散点(样本点)
# datasets.m
from sklearn.datasets import make_blobs
# 按照传入的参数 去产生散点
# n_samples=100, n_features=2, centers=None
# n_samples 用来指定要产生多少个样本点
# n_features 用来指定每个样本有几个特征
# centers 指定是有几个分类的中心 可以传入一个整数(表示有几个分类)
X_train,y_train = make_blobs(n_samples=200,n_features=2,centers=4)
X_train
plt.scatter(X_train[:,0],X_train[:,1],c=y_train)
plt.scatter(X_train[:,0],X_train[:,1])

建立模型,训练数据,并进行数据预测,使用相同数据

# 使用kmeans算法做聚类
# 获取模型
from sklearn.cluster import KMeans
# n_clusters=8 n_clusters用来指定分成多少簇 默认分8簇
# 我们可以通过指定n_clusters的值 来设置分成几个类型
kmeans = KMeans(n_clusters=8)
# 训练模型
kmeans.fit(X_train)
y_ = kmeans.predict(X_train)
#绘制图形,显示聚类结果kmeans.cluster_centers
plt.scatter(X_train[:,0],X_train[:,1],c=y_train)
# 这回使用kmeans预测出来的分类y_ 来上色
plt.scatter(X_train[:,0],X_train[:,1],c=y_)

实战,三问中国足球几多愁?

#导包,3D图像需导包:
from mpl_toolkits.mplot3d import Axes3D
#读取数据
AsiaFootball.csv
#列名修改为:"国家","2006世界杯","2010世界杯","2007亚洲杯"
df = pd.read_csv('./data/AsiaFootball.csv',header=None)
df.columns = ["国家","2006世界杯","2010世界杯","2007亚洲杯"]
df
#使用K-Means进行数据处理,对亚洲球队进行分组,分三组
kmeans = KMeans(n_clusters=3)
X_train = df.iloc[:,1:]  # 后三列的数据 作为训练集(国家名字就不要了)
# 训练模型
kmeans.fit(X_train)
# 使用模型去预测
kmeans.predict(X_train)
# 如果fit和predict使用的是同一个数据集 可以使用fit_predict 训练并预测
y_ = kmeans.fit_predict(X_train)
y_  # y_中的顺序 是按照样本的顺序来的
df
y_==1
df[y_==0]
df[y_==1]
df[y_==2]['国家']
#for循环打印输出分组后的球队,每一组球队打印一行
for i in range(3):
    # print(i)
    # print(df[y_==i]['国家'])
    s = df[y_==i]['国家']
    for country in s:
        print(country,end=' ')
    print('\n')

绘制三维立体图形

  • ax = plt.subplot(projection = ‘3d’)

  • ax.scatter3D()

    from mpl_toolkits.mplot3d import Axes3D
    df.head()
    df
    centers = kmeans.cluster_centers_
    centers
    plt.figure(figsize=(12,8))
    axes = plt.subplot(projection=‘3d’)

    传入 x y z

    x = df[‘2006世界杯’]
    y = df[‘2010世界杯’]
    z = df[‘2007亚洲杯’]
    axes.scatter(x,y,z,c=y_,s=200)
    axes.scatter(centers[:,0],centers[:,1],centers[:,2])
    axes.set_xlabel(‘2006世界杯’,fontproperties=‘KaiTi’,fontsize=35)
    axes.set_ylabel(‘2010世界杯’,fontproperties=‘KaiTi’,fontsize=35)
    axes.set_zlabel(‘2007亚洲杯’,fontproperties=‘KaiTi’,fontsize=35)

2、聚类实践与常见错误

导包,使用make_blobs创建样本点

第一种错误,k值不合适,make_blobs默认中心点三个

# random_state随机数的种子
X_train,y_train = make_blobs(n_samples=1500,n_features=2,centers=3,random_state=2)
plt.scatter(X_train[:,0],X_train[:,1],c=y_train)
kmeans = KMeans(n_clusters=8)
y_ = kmeans.fit_predict(X_train)
plt.scatter(X_train[:,0],X_train[:,1],c=y_)
# 可以多尝试几个k的值 来看分类效果

第二种错误:标准差cluster_std不相同

# cluster_std 指的是没一簇(每一个分类)中的 数据和中心的偏离情况
X_train,y_train = make_blobs(n_samples=150,n_features=2,centers=3,cluster_std=[0.5,1,5],random_state=2)
plt.scatter(X_train[:,0],X_train[:,1],c=y_train)
kmeans = KMeans(n_clusters=3)
y_ = kmeans.fit_predict(X_train)
plt.scatter(X_train[:,0],X_train[:,1],c=y_)
# 不同组的 特征值的 范围不一样
# 像这样的数据 本身 就不适合用来分类(再去挖掘一些其他的特征值)

第三种错误,数据存在较大的各向异性

trans = [[0.6,-0.6],[-0.4,0.8]]

X2 = np.dot(X,trans) # 把数据压扁

trans = [[0.6,-0.6],[-0.4,0.8]]
X_train2 = np.dot(X_train,trans)
y_train2 = y_train
plt.scatter(X_train2[:,0],X_train2[:,1],c=y_train)
# 使用kmeans来 聚类
kmeans = KMeans(n_clusters=3)
y_ = kmeans.fit_predict(X_train2)  # 使用压扁了的数据 进行预测
plt.scatter(X_train2[:,0],X_train2[:,1],c=y_)
# 遇到存在各向异性的数据(各个方向差异比较大的情况)
# 对各个特征进行归一化处理

第四个错误:样本数量不同

X,y = make_blobs(n_samples=1500,n_features=2,centers=3)
pd.Series(y).unique()  # y一共是三类 分别是 0 1 2
# 目标值是0的所有样本 一共500个
# make_blobs尝试的样本 非常均衡 每个分类都有500个样本
X[y==0].shape
X[y==1].shape
X[y==2].shape
X0 = X[y==0][0:500]  # 0这个分类 取 500个
X1 = X[y==1][0:100]  # 1这个分类 取 100个
X2 = X[y==2][0:10]  # 2这个分类 取 10个
X_train = np.concatenate((X0,X1,X2))
y_train = [0]*500+[1]*100+[2]*10
plt.scatter(X_train[:,0],X_train[:,1],c=y_train)
kmeans = KMeans(n_clusters=3)
y_ = kmeans.fit_predict(X_train)
plt.scatter(X_train[:,0],X_train[:,1],c=y_)  # 使用预测出来的 分类作为渲染颜色的依据
# 样本数量差别很大 就不适合 使用kmeans了
# 在训练机器学习模型的时候 如果各个分类的样本 量差异很大
# 样本缩放
# 1000 10000
# 50 500
# 这里说的这种 处理样本量 差异很大的问题 是 用在 分类问题上的(聚类问题不适用)

小练习:

如果从 0-255这256(16x16)种颜色 中 抽取出 16种(4x4)
则在保存的时候 如果是保存成png格式的图片 图片的元数据中会自动建立颜色索引 从而压缩数据量
试试吧!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值