11-SVM与K均值聚类

一.SVM

什么是SVM?

SVM主要针对小样本数据进行学习、分类和预测(有时也叫回归)的一种方法,能解决神经网络不能解决的过学习问题,而且有很好的泛化能力

1.1 SVM原理

举个例子:
好吧,故事是这样子的:

在很久以前的情人节,大侠要去救他的爱人,但魔鬼和他玩了一个游戏。

魔鬼在桌子上似乎有规律放了两种颜色的球,说:“你用一根棍分开它们?要求:尽量在放更多球之后,仍然适用。”


1.png

于是大侠这样放,干的不错?.png

然后魔鬼,又在桌上放了更多的球,似乎有一个球站错了阵营.png

SVM就是试图把棍放在最佳位置,好让在棍的两边有尽可能大的间隙.png

现在即使魔鬼放了更多的球,棍仍然是一个好的分界线.png

增加难度


然后,在SVM 工具箱中有另一个更加重要的 trick。 魔鬼看到大侠已经学会了一个trick,于是魔鬼给了大侠一个新的挑战.png

现在,大侠没有棍可以很好帮他分开两种球了,现在怎么办呢?当然像所有武侠片中一样大侠桌子一拍,球飞到空中。然后,凭借大侠的轻功,大侠抓起一张纸,插到了两种球的中间.png

现在,从魔鬼的角度看这些球,这些球看起来像是被一条曲线分开了.png

再后来
无聊的大人们,把这些球叫做 「data」,把棍子 叫做 「classifier」, 最大间隙trick 叫做「optimization」, 拍桌子叫做「kernelling」, 那张纸叫做「hyperplane」
1.2 SVM实战:线性

直线斜率计算公式:k=(y2-y1)/(x2-x1)
1.导入

import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline
from sklearn.svm import SVC

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

np.random.seed(0)
X = np.r_[np.random.randn(20,2) - [2,2], np.random.randn(20,2)+[2,2]]
y = [0]*20 + [1]*20

clf = SVC(kernel='linear')
# 第一步:训练
clf.fit(X,y)

3.提取系数获取斜率

# 提取出系数
w = clf.coef_[0]
# 斜率 k=(y2-y1)/(x2-x1)
a = -w[0]/w[1]

4.线性方程的截距

# 分类边界
xx = np.linspace(-5,5)
#intercept截距/X轴方向的系数 == 线性方程的截距
yy = a*xx -(clf.intercept_[0])/w[1]

5.上边界和下边界

# 下边界
b = clf.support_vectors_[0]
yy_down = a*xx + (b[1]-a*b[0])

# 上边界
b = clf.support_vectors_[-1]
yy_up = a*xx + (b[1]-a*b[0])

6.绘制图形

# 画出三个边界
plt.figure(figsize=(12,8))
plt.plot(xx,yy,'k-')
plt.plot(xx,yy_down,'k--')
plt.plot(xx,yy_up,'k--',c = 'r')

# 画出支持向量
plt.scatter(clf.support_vectors_[:,0],clf.support_vectors_[:,1],s=200)
# 画出所有点
plt.scatter(X[:,0],X[:,1],c=y)
线性.png
1.3 SVM实战:基于半径(rbf)

1.导入

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

2.创造-3到3范围的点以及meshgrid

xx, yy = np.meshgrid(np.linspace(-3, 3, 500),
                     np.linspace(-3, 3, 500))
np.random.seed(0)
X = np.random.randn(300, 2)
#xor异或
Y = np.logical_xor(X[:, 0] > 0, X[:, 1] > 0)

3.创造模型(rbf),训练数据

clf = svm.SVC(kernel='rbf')
clf.fit(X, Y)

4.绘制图形

plt.figure(figsize=(8,8))

# 样本xy到分离超平面的距离
Z = clf.decision_function(np.c_[xx.ravel(), yy.ravel()])
Z = Z.reshape(xx.shape)
plt.imshow(Z,extent=(xx.min(), xx.max(), yy.min(), yy.max()), 
            cmap=plt.cm.PuOr_r)
#绘制轮廓
# contours = plt.contour(xx, yy, Z)

plt.scatter(X[:, 0], X[:, 1], s=30, c=Y, cmap=plt.cm.Paired,
            edgecolors='k')
plt.axis('off')
plt.axis([-3, 3, -3, 3])
plt.show()
基于半径.png
1.4 SVM实战:使用多种核函数对iris数据集进行分类

1.导入

from sklearn.svm import SVC
from sklearn.svm import LinearSVC
from sklearn import datasets 

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

iris = datasets.load_iris()

# 只取两个特征(方便画图)
X = iris.data[:,:2]
y = iris.target

# 建立模型
svc_linear = SVC(kernel='linear')
svc_rbf = SVC(kernel='rbf')#Radial Based Function 基于半径的函数
svc_poly = SVC(kernel='poly') # poly是多项式的意思
linear_svc = LinearSVC() # SVC(kernel = 'linear')相近方法更多,可以处理更多的数据

# 训练模型
svc_linear.fit(X,y)
svc_rbf.fit(X,y)
svc_poly.fit(X,y)
linear_svc.fit(X,y)

3.图片背景云点

# 网格密度
h = 0.02

# 设置x轴y轴的界限
x_min,x_max = X[:,0].min()-1, X[:,0].max()+1
y_min,y_max = X[:,1].min()-1, X[:,1].max()+1
# 得到网格的坐标
xx,yy = np.meshgrid(np.arange(x_min,x_max,h),
                   np.arange(y_min,y_max,h))

4.绘制图形

# 设置图片标题
titles = ['svc_linear',
         'svc_rbf',
         'svc_poly',
         'linear_svc']

plt.figure(figsize=(12,8))

# 在2*2子图中画出四种SVC
for i,clf in enumerate((svc_linear,svc_rbf,svc_poly,linear_svc)):
    plt.subplot(2,2,i+1)
    Z = clf.predict(np.c_[xx.ravel(),yy.ravel()])
    Z = Z.reshape(xx.shape)
    # 等高线以及背景
    plt.contourf(xx,yy,Z,alpha=0.2,cmap = 'cool')
    
    # 实际点的图
    plt.scatter(X[:,0],X[:,1],c=y,cmap='rainbow')
    plt.title(titles[i])
分类.png
1.5 使用SVM多种核函数进行回归

1.导入

from sklearn.svm import SVR
import numpy as np

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

#自定义样本点
X = 5*np.random.rand(40,1)
X.sort(axis = 0)
y = np.sin(X).ravel()

#添加噪声
y[::5] += 3*(0.5 - np.random.rand(8))

#建立模型
svr_linear = SVR(kernel='linear')
svr_rbf = SVR(kernel = 'rbf')
svr_poly = SVR(kernel = 'poly')

#训练并预测
p_y_linear = svr_linear.fit(X,y).predict(X)
p_y_rbf = svr_rbf.fit(X,y).predict(X)
p_y_poly = svr_poly.fit(X,y).predict(X)

3.绘制图形

# 画图
plt.figure(figsize=(12,8))
# 画出真实样本点
plt.scatter(X,y,c='k',label='data')
# 画出预测曲线
plt.plot(X,p_y_linear,c='navy',label='linear')
plt.plot(X,p_y_rbf,c='r',label='rbf')
plt.plot(X,p_y_poly,c='g',label='poly')
plt.legend()
回归.png

二.K-Means

什么是K-means?

K均值算法(K-means)聚类
关键词:K个种子,均值
聚类的概念:一种无监督的学习,事先不知道类别,自动将相似的对象归到同一个簇中

K-Means算法是一种聚类分析(cluster analysis)的算法,其主要是来计算数据聚集的算法,主要通过不断地取离种子点最近均值的算法
K-Means算法的思想很简单,对于给定的样本集,按照样本之间的距离大小,将样本集划分为K个簇。让簇内的点尽量紧密的连在一起,而让簇间的距离尽量的大

2.1 K-Means原理

欧氏距离


欧氏距离.png

步骤图


步骤图.png
2.2 K-Means主要最重大的缺陷——都和初始值有关

K是事先给定的,这个K值的选定是非常难以估计的。很多时候,事先并不知道给定的数据集应该分成多少个类别才最合适。(ISODATA算法通过类的自动合并和分裂,得到较为合理的类型数目K)
K-Means算法需要用初始随机种子点来搞,这个随机种子点太重要,不同的随机种子点会有得到完全不同的结果。(K-Means++算法可以用来解决这个问题,其可以有效地选择初始点)

2.3 K-Means步骤总结

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

2.4 K-Means算法应用

看到这里,你会说,K-Means算法看来很简单,而且好像就是在玩坐标点,没什么真实用处。而且,这个算法缺陷很多,还不如人工呢。是的,前面的例子只是玩二维坐标点,的确没什么意思。但是你想一下下面的几个问题:
1)如果不是二维的,是多维的,如5维的,那么,就只能用计算机来计算了。
2)二维坐标点的X,Y 坐标,其实是一种向量,是一种数学抽象。现实世界中很多属性是可以抽象成向量的,比如,我们的年龄,我们的喜好,我们的商品,等等,能抽象成向量的目的就是可以让计算机知道某两个属性间的距离。如:我们认为,18岁的人离24岁的人的距离要比离12岁的距离要近,鞋子这个商品离衣服这个商品的距离要比电脑要近,等等。

2.5 K-Means实战
  • make_blobs随机生成点
    1.导包随机生成数据
from sklearn.cluster import KMeans

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

#生成样本点
X_train,y_train = make_blobs(n_samples=300,centers=4,cluster_std=  0.6, random_state = 9)

2.建立模型

# 建立模型
kmeans = KMeans(n_clusters=4)
kmeans.fit(X_train)
y_ = kmeans.predict(X_train)

3.画图

#画图
plt.figure(figsize = (12,8))
centers = kmeans.cluster_centers_
plt.scatter(X_train[:,0],X_train[:,1],c = y_)
plt.scatter(centers[:,0],centers[:,1],c = 'r',s = 100,alpha = 0.4)
make_blobs.png
  • 三问中国足球几多愁
    1.导包读取数据
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
%matplotlib inline
from mpl_toolkits.mplot3d import Axes3D
from sklearn.cluster import KMeans
data = pd.read_csv('../data/AsiaZoo.txt',header = None)

2.处理数据修改列名

#处理数据,添加列名
data.columns = ["国家","2006世界杯","2010世界杯","2007亚洲杯"]

3.建立模型

#使用K-Means进行数据处理
kMeans = KMeans(n_clusters=3)
X_train = data[['2006世界杯','2010世界杯','2007亚洲杯']]
y_ = kMeans.fit(X_train).predict(X_train)

4.根据模型将这些国家按照水平进行分类

country = data['国家']
for i in range(3):
    ind = np.argwhere(kMeans.predict(X_train) == i)
    result  = country[ind.ravel()]
    for i in result.index:
        print(result[i],end = ' ')
    print('\n')

#输出结果是:
伊朗 沙特 乌兹别克斯坦 巴林 朝鲜 

日本 韩国 

中国 伊拉克 卡塔尔 阿联酋 泰国 越南 阿曼 印尼 

5.画图

#绘制三维立体图,将各个国家画到3D图中
centers = kMeans.cluster_centers_#KMeans算法得到的中心店
x,y,z = data['2006世界杯'],data['2010世界杯'],data['2007亚洲杯']
plt.figure(figsize = (12,8))
ax=plt.subplot(111,projection='3d')
ax.scatter3D(x,y,z,c = kMeans.predict(X_train),cmap='cool')  
ax.scatter3D(centers[:,0],centers[:,1],centers[:,2],c = kMeans.predict(centers),s = 300,cmap = "rainbow")
ax.set_xlabel("X")  
ax.set_ylabel("Y")  
ax.set_zlabel("Z")  
plt.show() 
国家足球.png
  • K-Means常见错误
    1.导包
import numpy as np
import matplotlib.pyplot as plt
from sklearn.cluster import KMeans
from sklearn.datasets import make_blobs

2.建立样本点

# 建立样本点
n_samples = 1500
random_state = 170
#默认情况下make_blobs有三个中心点
X,y = make_blobs(n_samples=n_samples,random_state=random_state)

第一种错误:incorrect number of cluster

#第一种错误,k值不合适,make_blobs默认中心点三个
y_ = KMeans(n_clusters=2).fit_predict(X)
#绘制图形
plt.figure(figsize = (12,8))
plt.subplot(221)
plt.scatter(X[:,0],X[:,1],c = y_)
错误1.png

第二种错误:数据偏差

#第二种错误,数据偏差
trans = [[0.6,-0.6],[-0.4,0.8]]
X2 = np.dot(X,trans)
y2_ = KMeans(n_clusters=3).fit_predict(X2)
#绘制图形
plt.figure(figsize = (12,8))
plt.subplot(222)
plt.scatter(X2[:,0],X2[:,1],c = y2_)
错误2.png

第三种错误:数据标准差不同

# 第三个错误:标准偏差
X3,y3 = make_blobs(n_samples=n_samples,
                  cluster_std = [1.0,2.5,0.5],
                  random_state = random_state)
y3_ = KMeans(n_clusters=3).fit_predict(X3)
plt.figure(figsize = (12,8))
plt.subplot(223)
plt.scatter(X3[:,0],X3[:,1],c=y3_)
plt.title('failed 3: unequal std')
错误3.png

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

# 第四个错误:样本数量不同
X4 = np.vstack((X[y==0][:500],X[y==1][:100],X[y==2][:10]))
y4_ = KMeans(n_clusters=3).fit_predict(X4)
plt.figure(figsize = (12,8))
plt.subplot(224)
plt.scatter(X4[:,0],X4[:,1],c=y4_)
plt.title('failed 4: unequal number of samples')
错误4.png
2.6 K-Means图片颜色点分类

1.导包

import numpy as np
import matplotlib.pyplot as plt
from sklearn.cluster import KMeans
from sklearn.metrics import pairwise_distances_argmin
from sklearn.datasets import load_sample_image
from sklearn.utils import shuffle
n_colors = 64

2.加载图片/创建模型/训练数据/获取labels

# 加载图片
china = load_sample_image("china.jpg")
# 图片颜色值转换成[0,1]之间float类型数据
china = np.array(china, dtype=np.float64) / 255

# 将3D的图片数据转换成2D数组.
w, h, d  = china.shape
image_array = np.reshape(china, (w * h, d))

#使用shuffle打乱数据,并进行训练
image_array_sample = shuffle(image_array, random_state=0)[:1000]
kmeans = KMeans(n_clusters=n_colors, random_state=0).fit(image_array_sample)

# 获取标签点
labels = kmeans.predict(image_array)

3.使用pairwise_distances_argmin算法生成随机labels

codebook_random = shuffle(image_array, random_state=0)[:n_colors]
labels_random = pairwise_distances_argmin(codebook_random,image_array,axis=0)

4.创造方法,重新合成图片

def recreate_image(codebook, labels, w, h):
    d = codebook.shape[1]
    image = np.zeros((w, h, d))
    label_idx = 0
    for i in range(w):
        for j in range(h):
            image[i][j] = codebook[labels[label_idx]]
            label_idx += 1
    return image

5.数据可视化

# 数据可视化
plt.figure(1)
plt.clf()
ax = plt.axes([0, 0, 1, 1])
plt.axis('off')
plt.title('Original image (96,615 colors)')
plt.imshow(china)

plt.figure(2)
plt.clf()
ax = plt.axes([0, 0, 1, 1])
plt.axis('off')
plt.title('Quantized image (64 colors, K-Means)')
plt.imshow(recreate_image(kmeans.cluster_centers_, labels, w, h))

plt.figure(3)
plt.clf()
ax = plt.axes([0, 0, 1, 1])
plt.axis('off')
plt.title('Quantized image (64 colors, Random)')
plt.imshow(recreate_image(codebook_random, labels_random, w, h))
plt.show()
颜色分类1.png

颜色分类2.png

颜色分类3.png

推荐阅读更多精彩内容