支持向量机
1 概念及定义
支持向量机是一个二类分类模型,基本模型的定义为:是在特征空间上的间隔最大的线性分类器
支持向量机学习的基本想法是求解能够正确划分训练数据集并且几何间隔最大的分离超平面.
二次规划是一类典型的优化问题,包括凸二次优化和非凸二次优化.
目标函数是变量的二次函数,约束条件是变量的线性不等式
核技巧(kernel trick):
一般用来解决非线性分类问题,将非线性问题转换成线性问题8
第一步:首先使用一个变换将原空间的数据映射到新空间
第二步:在新的空间里用线性分类学习方法从训练数据中学习分类模型
2.序列最小最优化算法
sequential minimal optimization SMO算法
核函数的理解:将一个欧式空间映射到希尔伯特空间的一个函数
核函数的选择是支持向量机的最大变数,核函数的选取一般也是按照经验公式来进行选取
例如:文本数据通常采用线性核,情况不明确的时候可以尝试高斯核
3.利用线性核&高斯核训练一个SVM,并比较支持向量的区别
3.1数据的读取和可视化处理
# 西瓜数据集的读取
import pandas as pd
with open('/home/dengshuo/GithubCode/ML/CH06/watermelon_3a.csv') as datafile:
df=pd.read_csv(datafile ,header=None)
print (df)
0 1 2 3
0 1 0.697 0.4600 1
1 2 0.774 0.3760 1
2 3 0.634 0.2640 1
3 4 0.608 0.3180 1
4 5 0.556 0.2150 1
5 6 0.403 0.2370 1
6 7 0.481 0.1490 1
7 8 0.437 0.2110 1
8 9 0.666 0.0910 0
9 10 0.243 0.0267 0
10 11 0.245 0.0570 0
11 12 0.343 0.0990 0
12 13 0.639 0.1610 0
13 14 0.657 0.1980 0
14 15 0.360 0.3700 0
15 16 0.593 0.0420 0
16 17 0.719 0.1030 0一些函数的解释:
read_csv() arg
header:
int or list of ints, default ‘infer’
Row number(s) to use as the column names, and the start of the data.
Default behavior is as if set to 0 if nonames
passed, otherwise
None
. Explicitly passheader=0
to be able to replace existing
names. The header can be a list of integers that specify row locations for
a multi-index on the columns e.g. [0,1,3]. Intervening rows that are not
specified will be skipped (e.g. 2 in this example is skipped). Note that
this parameter ignores commented lines and empty lines if
skip_blank_lines=True
, so header=0 denotes the first line of data
rather than the first line of the file.
# 制作表头 : 将每列数据填上标签,将每列数据进行命名,
# 当原始的数据中含有名字时,可以直接进行读取
# make header
df.columns=['id','density','sugar_content','label']
print(df)
- id density sugar_content label 0 1 0.697 0.4600 1 1 2 0.774 0.3760 1 2 3 0.634 0.2640 1 3 4 0.608 0.3180 1 4 5 0.556 0.2150 1 5 6 0.403 0.2370 1 6 7 0.481 0.1490 1 7 8 0.437 0.2110 1 8 9 0.666 0.0910 0 9 10 0.243 0.0267 0 10 11 0.245 0.0570 0 11 12 0.343 0.0990 0 12 13 0.639 0.1610 0 13 14 0.657 0.1980 0 14 15 0.360 0.3700 0 15 16 0.593 0.0420 0 16 17 0.719 0.1030 0
# 更改索引列 df.set_index 将原先按第一列的数据,按要求的列进行索引
df.set_index(['id'])
density | sugar_content | label | |
---|---|---|---|
id | |||
1 | 0.697 | 0.4600 | 1 |
2 | 0.774 | 0.3760 | 1 |
3 | 0.634 | 0.2640 | 1 |
4 | 0.608 | 0.3180 | 1 |
5 | 0.556 | 0.2150 | 1 |
6 | 0.403 | 0.2370 | 1 |
7 | 0.481 | 0.1490 | 1 |
8 | 0.437 | 0.2110 | 1 |
9 | 0.666 | 0.0910 | 0 |
10 | 0.243 | 0.0267 | 0 |
11 | 0.245 | 0.0570 | 0 |
12 | 0.343 | 0.0990 | 0 |
13 | 0.639 | 0.1610 | 0 |
14 | 0.657 | 0.1980 | 0 |
15 | 0.360 | 0.3700 | 0 |
16 | 0.593 | 0.0420 | 0 |
17 | 0.719 | 0.1030 | 0 |
# 数据进行可视化处理
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
fig=plt.figure()
ax=fig.add_subplot(111)
ax.scatter(df['density'],df['sugar_content'])
plt.show()
![数据相关关系](https://img-blog.csdn.net/20180425103759518?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzM3OTA0OTQ1/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70) 可以画出一个最基本的图形,但是这个只能反映出两个变量之间的函数关系 没有显示出好坏瓜与两个变量之间的联系.label 没有表现出来
# 利用matplotlib & seaborn 来进行画图
plt.figure(0)
sns.FacetGrid(df,hue='label',size=5).map(plt.scatter,'density','sugar_content').add_legend()
plt.show()
![这里写图片描述](https://img-blog.csdn.net/20180425103917378?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzM3OTA0OTQ1/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70)
df[['density','sugar_content']].values
array([[ 0.697 , 0.46 ],
[ 0.774 , 0.376 ],
[ 0.634 , 0.264 ],
[ 0.608 , 0.318 ],
[ 0.556 , 0.215 ],
[ 0.403 , 0.237 ],
[ 0.481 , 0.149 ],
[ 0.437 , 0.211 ],
[ 0.666 , 0.091 ],
[ 0.243 , 0.0267],
[ 0.245 , 0.057 ],
[ 0.343 , 0.099 ],
[ 0.639 , 0.161 ],
[ 0.657 , 0.198 ],
[ 0.36 , 0.37 ],
[ 0.593 , 0.042 ],
[ 0.719 , 0.103 ]])利用seaborn可以表示三个维度 row ,columns,hue hue 利用颜色的不同来进行区分
3.2 调用机器学习包来实现算法
下面是一个最简单的基本流程,可以用来模仿help(plt.scatter)
scatter(x, y, s=None, c=None, marker=None, cmap=None, norm=None, vmin=None, vmax=None, alpha=None, linewidths=None, verts=None, edgecolors=None, hold=None, data=None, **kwargs)
help(plt.pcolorsmesh)
pcolormesh(*args, **kwargs)
Plot a quadrilateral mesh. 绘制一个四边形网格help(np.meshgrid)
meshgrid(*xi, **kwargs)
Return coordinate matrices from coordinate vectors.从坐标向量返回坐标矩阵
Make N-D coordinate arrays for vectorized evaluations of
N-D scalar/vector fields over N-D grids, given
one-dimensional coordinate arrays x1, x2,…, xn.
# import library
from sklearn import svm
# assumed you have X (predictor) and Y(target)
#Create SVM classification object
model=svm.SVC(C=1000,kernel='rbf') # Penalty parameter C of the error term.
# 这个C 是个错误项的惩罚参数
# 可直接通过改变核函数来进行
# 或者定义一个循环来进行
# for fig_num ,kernel in enumerate(('linear','rbf')):
# model=svm.SVC(C=1000,kernel=kernel)
# 涉及的变量进行修改
# train the model using the training sets and check score
X=df[['density','sugar_content']].values
y=df['label'].values
model.fit(X,y)
# get support vectors
sv=model.support_vectors_
# draw decision zone
plt.figure('rbf')
plt.clf()
# plot point and mark out support vectors
plt.scatter(X[:,0],X[:,1],edgecolors='k',c=y,cmap=plt.cm.Paired,zorder=10)
# 只有这一个 zorder 参数没有看懂,不是很明白是什么意思
plt.scatter(sv[:,0],sv[:,1],edgecolors='k',facecolors='none',s=80,linewidths=2,zorder=10)
# plot the decision boundary and decision zone into a color plot
x_min,x_max=X[:,0].min()-0.2 ,X[:,0].max()+0.2
y_min,y_max=X[:,1].min()-0.2 ,X[:,1].max()+0.2
XX,YY=np.meshgrid(np.arange(x_min,x_max,0.02),np.arange(y_min,y_max,0.02))
Z=model.decision_function(np.c_[XX.ravel(),YY.ravel()])
# decision_function(X) method of sklearn.svm.classes.SVC instance
# Distance of the samples X to the separating hyperplane.
Z=Z.reshape(XX.shape)
plt.pcolormesh(XX,YY,Z>0,cmap=plt.cm.Paired)
plt.contour(XX,YY,Z,colors=['k','k','k'],linestyles=['--','-','--'],levels=[-.5,0,.5])
plt.title('svm:kernel=rbf')
plt.axis('tight')
plt.xlabel('density')
plt.ylabel('sugar_content')
plt.show()
![这里写图片描述](https://img-blog.csdn.net/20180425103944765?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzM3OTA0OTQ1/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70)
4. 利用西瓜数据集3.0a ,密度”density”为输入,含糖率”sugar_content”为输出.训练一个SVR
df.columns=['id','density','sugar_content','label']
df.set_index(['id'])
density | sugar_content | label | |
---|---|---|---|
id | |||
1 | 0.697 | 0.4600 | 1 |
2 | 0.774 | 0.3760 | 1 |
3 | 0.634 | 0.2640 | 1 |
4 | 0.608 | 0.3180 | 1 |
5 | 0.556 | 0.2150 | 1 |
6 | 0.403 | 0.2370 | 1 |
7 | 0.481 | 0.1490 | 1 |
8 | 0.437 | 0.2110 | 1 |
9 | 0.666 | 0.0910 | 0 |
10 | 0.243 | 0.0267 | 0 |
11 | 0.245 | 0.0570 | 0 |
12 | 0.343 | 0.0990 | 0 |
13 | 0.639 | 0.1610 | 0 |
14 | 0.657 | 0.1980 | 0 |
15 | 0.360 | 0.3700 | 0 |
16 | 0.593 | 0.0420 | 0 |
17 | 0.719 | 0.1030 | 0 |
X=df['density']
y=df['sugar_content']
plt.figure()
plt.scatter(X,y,c='g')
plt.xlabel('density')
plt.ylabel('sugar_content')
plt.show()
# 但是这个图 没办法显示 好坏 瓜的关系 应该还有其他的办法
# 试着调用机器学习包
from sklearn import svm
svr=svm.SVR()
X=df['density'].values
y=df['sugar_content'].values
svr.fit(X,y)
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from sklearn.svm import SVR # for SVR model
from sklearn.model_selection import GridSearchCV # for optimal parameter search
# loading data
df = pd.read_csv('/home/dengshuo/GithubCode/ML/CH06/watermelon_3a.csv', header=None, )
df.columns = ['id', 'density', 'sugar_content', 'label']
df.set_index(['id'])
X = df[['density']].values
y = df[['sugar_content']].values
# generate model and fitting
# linear
# svr = GridSearchCV(SVR(kernel='linear'), cv=5, param_grid={"C": [1e0, 1e1, 1e2, 1e3]})
# rbf
# svr = GridSearchCV(SVR(kernel='rbf'), cv=5, param_grid={"C": [1e-4, 1e-3, 1e-2, 1e-1, 1, 1e1, 1e2, 1e3, 1e4]})
# ploy
svr = GridSearchCV(SVR(kernel='poly'), cv=5, param_grid={"C": [1e-4, 1e-3, 1e-2, 1e-1, 1, 1e1, 1e2, 1e3, 1e4]})
svr.fit(X, y)
sv_ratio = svr.best_estimator_.support_.shape[0] / len(X)
print("Support vector ratio: %.3f" % sv_ratio)
y_svr = svr.predict(X)
sv_ind = svr.best_estimator_.support_
plt.scatter(X[sv_ind], y[sv_ind], c='r', s=50, label='SVR support vectors', zorder=2)
plt.scatter(X, y, c='k', label='data', zorder=1)
plt.plot(X, y_svr, c='orange', label='SVR fit curve with poly kernel')
plt.xlabel('density')
plt.ylabel('sugar_ratio')
plt.title('SVR on watermelon3.0a')
plt.legend()
plt.show()