





SVM:寻找支持向量、预测:
from sklearn import svm
X = [[2, 0], [1, 1], [2,3]]
Y = [0, 0, 1]
clf = svm.SVC(kernel = 'linear')
clf.fit(X, Y)
# 查看模型
print(clf) # output: SVC(C=1.0, class_weight=None, ...)
# 打印出支持向量
print(clf.support_vectors_) # [[ 1. 1.], [ 2. 3.]]
# 支持向量在数据集中的索引
print(clf.support_) # output: [1, 2]
# 各类结果中的支持向量的个数
print(clf.n_support_) # output: [1, 1]
# 预测
print(clf.predict([[2, 2]])) # output: [1]
结果如下:
SVC(C=1.0, cache_size=200, class_weight=None, coef0=0.0,
decision_function_shape='ovr', degree=3, gamma='auto', kernel='linear',
max_iter=-1, probability=False, random_state=None, shrinking=True,
tol=0.001, verbose=False)
[[1. 1.]
[2. 3.]]
[1 2]
[1 1]
[1]

线性支持向量机:可分情况
——使用svm寻找二维数据的决策平面:
#构造模型
# coding: utf-8
import numpy as np
from sklearn import svm
np.random.seed(0) # 使用相同的seed()值,则每次生成的随机数都相同
# 创建可线性分类的数据集与结果集
X = np.r_[np.random.randn(20, 2) - [2, 2], np.random.randn(20,2) + [2, 2]]#一部分是在-2, -2附近的正态分布;另一部分是2, 2附近正态分布
Y = [0] * 20 + [1] * 20#*就是把列表复制了20份,+就是把列表连起来,所以最后就是[0……]+[1……]就是[0……1……]
# 构造 SVM 模型
clf = svm.SVC(kernel='linear')
clf.fit(X, Y) # 训练
结果如下
SVC(C=1.0, cache_size=200, class_weight=None, coef0=0.0,
decision_function_shape='ovr', degree=3, gamma='auto', kernel='linear',
max_iter=-1, probability=False, random_state=None, shrinking=True,
tol=0.001, verbose=False)
#收集这些数据来画平面图,因为这是一个二维的模型,因此可以假设超平面方程为 w0x + w1y + b = 0 转为点斜式就是: y = -(w0/w1)x - (b/w1) :
#这样就从超平面中取了若干个点,用于画直线用
w = clf.coef_[0]#赋予特征的权重(原始问题中的系数),这仅适用于线性内核。[0]就是取第一个
a = -w[0] / w[1] # 斜率
xx = np.linspace(-5, 5) # 在区间[-5, 5] 中产生连续的值,用于画线
yy = a * xx - (clf.intercept_[0]) / w[1]#clf.intercept_决策函数中的常量[0]就是取第一个
#找出与超平面平行并通过支持向量的直线找出来,因为这三条线是平行的,所以斜率一样,只有截距不一样。
b = clf.support_vectors_[0] # 第一个分类的支持向量;[0]也是一个索引,是正数第一个
yy_down = a * xx + (b[1] - a * b[0])
b = clf.support_vectors_[-1] # 第二个分类中的支持向量;[-1]就是倒数第一个
yy_up = a * xx + (b[1] - a * b[0])
import pylab as pl
pl.plot(xx, yy, 'k-')
pl.plot(xx, yy_down, 'k--')
pl.plot(xx, yy_up, 'k--')
pl.scatter(clf.support_vectors_[:, 0], clf.support_vectors_[:, 1],
s=80, facecolors='none')
pl.scatter(X[:, 0], X[:, 1], c=Y, cmap=pl.cm.Paired)
pl.axis('tight')
pl.show()
%matplotlib inline


线性支持向量机:不可分情况
——使用svm寻找不到二维数据的决策平面:
import numpy as np
from sklearn import svm
from matplotlib import pyplot as plt
%matplotlib inline
training_data = np.random.randint(-100, 100, size=(100, 2))
xs = training_data[:, 0]#是一个矩阵,就是表示,第0列的所有
ys = training_data[:, 1]#表示,第1列的所有
training_label = np.array(((np.multiply(xs, ys)) < 0), dtype=np.int)
training_label[training_label == 0] = -1
#print(training_label)
#print(training_data)
plt.plot(training_data[:, 0][training_label == 1], training_data[:, 1][training_label == 1], 'bo')
plt.plot(training_data[:, 0][training_label == -1], training_data[:, 1][training_label == -1], 'r^')

# 构造 SVM 模型
clf = svm.SVC(kernel='linear')
clf.fit(training_data, training_label) # 训练
结果如下
SVC(C=1.0, cache_size=200, class_weight=None, coef0=0.0,
decision_function_shape='ovr', degree=3, gamma='auto', kernel='linear',
max_iter=-1, probability=False, random_state=None, shrinking=True,
tol=0.001, verbose=False)
#收集这些数据来画平面图,因为这是一个二维的模型,因此可以假设超平面方程为 w0x + w1y + b = 0 转为点斜式就是: y = -(w0/w1)x - (b/w1) :
#这样就从超平面中取了若干个点,用于画直线用
w = clf.coef_[0]#赋予特征的权重(原始问题中的系数),这仅适用于线性内核。[0]就是取第一个
a = -w[0] / w[1] # 斜率
xs = np.linspace(-5, 5) # 在区间[-5, 5] 中产生连续的值,用于画线
ys = a * xs - (clf.intercept_[0]) / w[1]#clf.intercept_决策函数中的常量[0]就是取第一个
#找出与超平面平行并通过支持向量的直线找出来,因为这三条线是平行的,所以斜率一样,只有截距不一样。
b = clf.support_vectors_[0] # 第一个分类的支持向量;[0]也是一个索引,是正数第一个
ys_down = a * xs + (b[1] - a * b[0])
b = clf.support_vectors_[-1] # 第二个分类中的支持向量;[-1]就是倒数第一个
ys_up = a * xs + (b[1] - a * b[0])
import pylab as pl
%matplotlib inline
pl.plot(xs, ys, 'k-')
pl.plot(xs, ys_down, 'k--')
pl.plot(xs, ys_up, 'k--')
pl.scatter(clf.support_vectors_[:, 0], clf.support_vectors_[:, 1],
s=80, facecolors='none')
pl.scatter(training_data[:, 0], training_data[:, 1], c=training_label, cmap=pl.cm.Paired)
pl.axis('tight')
pl.show()



import numpy as np
from matplotlib import pyplot as plt
%matplotlib inline
theta = 180 * np.random.rand(1000)
xs = np.concatenate([np.array([np.cos(theta), np.sin(theta)]).T, np.array([2 * np.cos(theta), 2 * np.sin(theta)]).T])
ys = np.array([0] * 1000 + [1] * 1000)
plt.plot(xs[: 1000, 0], xs[: 1000, 1], 'r.', xs[1000:, 0], xs[1000:, 1], 'b.')
结果如下

def transform1(xs):
return np.sqrt(xs[:, 0] ** 2 + xs[:, 1] ** 2)
xs1 = transform1(xs)
plt.plot(np.zeros_like(xs1[: 1000]), xs1[: 1000], 'r.', np.zeros_like(xs1[1000:]), xs1[1000:], 'b.')
结果如下

def transform2(xs):
return np.array([np.sqrt(xs[:, 0] ** 2 + xs[:, 1] ** 2), np.arctan(xs[:, 1] / xs[:, 0])]).T
xs2 = transform2(xs)
plt.plot(xs2[: 1000, 0], xs2[: 1000, 1], 'r.', xs2[1000:, 0], xs2[1000:, 1], 'b.')
结果如下



非线性支持向量机
——使用sklearn核函数来实现XOR问题的分类
import matplotlib.pyplot as plt
import matplotlib.image as mpimg
import matplotlib as mpl
from PIL import Image
from sklearn import svm
import numpy as np
%matplotlib inline
if __name__ == "__main__":
#随机生成200个点
x_xor = np.random.randn(200,2)
#将数据集变成一个异或的数据集
#都满足或者都不满足条件返回False,否则返回True
y_xor = np.logical_xor(x_xor[:,0] > 0,x_xor[:,1] > 0)
#三元运算符,为True返回1或者返回-1
y_xor = np.where(y_xor,1,-1)
#描点
#绘制标签为1的点
plt.scatter(x_xor[y_xor==1,0],x_xor[y_xor==1,1],c="b",marker="x",label="1")
#绘制标签为-1的点
plt.scatter(x_xor[y_xor==-1,0],x_xor[y_xor==-1,1],c="r",marker="s",label="-1")
plt.ylim(-3.0)
plt.legend()
plt.show()
#plot_decision_regions函数,划分决策区域
def plot_decision_regions(x,y,model,resolution=0.02):
#定义标记符
markers = ('s','x','o','^','v')
#定义颜色
colors = ('red','blue','lightgreen','gray','cyan')
#ListedColormap方法是将标记符和颜色进行对应
#在绘图的时候红色表示正方形而蓝色表示叉
cmap = mpl.colors.ListedColormap(colors[:len(np.unique(y))])
#获取第一个特征中最大值加1和最小值减1
x1_min,x1_max = x[:,0].min() - 1,x[:,0].max() + 1
#获取第二个特征中最大值加1和最小值减1
x2_min,x2_max = x[:,1].min() - 1,x[:,1].max() + 1
#根据特上面获取到特征的最大最小值构建一个网格坐标
#通过模拟足够多的数据,来绘制出决策边界
#resolution表示网格的大小
'''
如一个2*2的网格坐标,网格大小为1,网格坐标点如下
(0,0),(0,1),(0,2)
(1,0),(1,1),(1,2)
(2,0),(2,1),(2,2)
'''
xx1,xx2 = np.meshgrid(np.arange(x1_min,x1_max,resolution), #numpy.meshgrid()——生成网格点坐标矩阵
np.arange(x2_min,x2_max,resolution))
z = model.predict(np.array([xx1.ravel(),xx2.ravel()]).T)
z = z.reshape(xx1.shape)
#绘制边界
plt.contourf(xx1,xx2,z,alpha=0.4,cmap=cmap)
#设置坐标的长度
plt.xlim(xx1.min(),xx1.max())
plt.ylim(xx2.min(),xx2.max())
for idx,cl in enumerate(np.unique(y)):
#绘点
plt.scatter(x=x[y == cl,0],y=x[y == cl,1],
alpha=0.8,c=cmap(idx),
marker=markers[idx],label=cl)
plt.xlabel("x1")
plt.ylabel("x2")
plt.show()
结果如下

#求出边界
if __name__ == "__main__":
#随机生成200个点
x_xor = np.random.randn(200,2)
#将数据集变成一个异或的数据集
#都满足或者都不满足条件返回False,否则返回True
y_xor = np.logical_xor(x_xor[:,0] > 0,x_xor[:,1] > 0)
#三元运算符,为True返回1或者返回-1
y_xor = np.where(y_xor,1,-1)
svm = svm.SVC(kernel="rbf", random_state=0, gamma=0.1, C=1.0)
svm.fit(x_xor, y_xor)
plot_decision_regions(x_xor, y_xor, svm)
结果如下























PCA+SVM用于人脸识别
#人脸数据集:有 1288 条实例,特征向量的维度是 1859 ,共有 7 种分类结果。
import time
from sklearn.datasets import fetch_lfw_people
#fetch_lfw_people这个函数是用来加载lfw人脸识别数据集的函数,
#返回data(人脸数据),images(人脸),target(人脸对应的人名编号),target_names(人名)
lfw_people = fetch_lfw_people(min_faces_per_person=70, resize=0.4)
n_samples, h, w = lfw_people.images.shape # 获取图像数据集的形状,绘图使用
# 获取特征数据集和结果集
X = lfw_people.data
Y = lfw_people.target
n_features = X.shape[1] # 特征的个数,或称为特征的维数
target_names = lfw_people.target_names # 数据集中有多少个人,以人名组成列表返回
n_classes = target_names.shape[0]
print("===== 数据集中信息 =====")
print("数据个数(n_samples):", n_samples) # output: 1288
print("特征个数,维度(n_features):", n_features) # output: 1859
print("结果集类别个数(n_classes):", n_classes) # output: 7
结果如下
===== 数据集中信息 =====
数据个数(n_samples): 1288
特征个数,维度(n_features): 1850
结果集类别个数(n_classes): 7
#拆分训练集和测试集
#将数据集分成训练集和测试集,这样的好处是,不用额外找图片作为测试集,而且从数据集中分离的数据,是包含分类结果的,这样有利于我们对结果预测的对比。
#利用 sklearn 中提供的 train_test_split 可以进行这样的划分:
from sklearn.model_selection import train_test_split
# 拆分训练集和测试集
X_train, X_test, Y_train, Y_test = train_test_split(X, Y, test_size=0.25)
#这个函数返回四个结果,训练集特征向量,测试集特征向量,训练集归类标记,测试集归类标记。
#特征降维处理
#原始数据的特征向量维度是非常高的(1859维),这就意味着,训练模型的复杂度非常高,因此,需要通过一定的手段将特征值进行降维操作,来提高性能。
#有时降维处理后的数据,反而能提高准确性,这是因为可以减少噪点带来的影响。本例子采用 PCA 的降维方法。
from sklearn.decomposition import PCA
n_components = 150#表示要保存的组件的数目,也即保留下来的特征个数 n,我们设置为目标维度为 150
t0 = time.time()#返回当前的时间戳
pca = PCA(n_components=n_components, whiten=True).fit(X_train)#调用PAC函数通过训练集进行降维模型的建模
print("pca done %0.3fs" % (time.time() - t0))
t0 = time.time()
X_train_pca = pca.transform(X_train)#再调用模型对象的 .transform 将训练集转化为降维后的数据。
X_test_pca = pca.transform(X_test)#再调用模型对象的 .transform 将测试集转化为降维后的数据。
print("data set to pca done %0.3fs" % (time.time() - t0))
# 从人脸中提取特征点
eigenfaces = pca.components_.reshape((n_components, h, w))#这是处理后的特征点,后续的图像可视化会用到这个
#构造SVM分类器
from sklearn import svm
from sklearn.model_selection import GridSearchCV
# 构造分类器
t0 = time.time()
param_grid = {
"C": [1e3, 5e3, 1e4, 1e5],
"gamma": [0.0001, 0.0005, 0.001, 0.005, 0.01, 0.1]
}
clf = GridSearchCV(svm.SVC(kernel='rbf', class_weight='balanced'), param_grid=param_grid)
#sklearn 的 SVM 模型有很多参数, param_grid 这个参数有什么用呢? C 是一个对错误的部分的惩罚;
#gamma 的参数是这样的,对于不同的核函数会有不同的表现,gamma 表示使用多少比例的特征点,因为我们不知道哪些参数会产生最好的结果,因此使用不同的参数来训练,然后选取训练最好的模型。
#因此使用不同值的 C 和不同值的 gamma ,进行多个量(5 x 6 = 30)的尝试,然后进行搜索,选出准确率最高的模型 ( 即代码中的 clf.best_estimator_ )
clf.fit(X_train_pca, Y_train)
print("fit done %0.3fs" % (time.time() - t0))
print(clf.best_estimator_)
结果如下
fit done 18.097s
SVC(C=1000.0, cache_size=200, class_weight='balanced', coef0=0.0,
decision_function_shape='ovr', degree=3, gamma=0.001, kernel='rbf',
max_iter=-1, probability=False, random_state=None, shrinking=True,
tol=0.001, verbose=False)
#预测
from sklearn.metrics import classification_report
from sklearn.metrics import confusion_matrix
# 预测
t0 = time.time()
#预测的通常都是调用模型的 .predict 的方法
y_pred = clf.predict(X_test_pca)
print("classification_report:")
#通过 classification_report 方法进行查看,可以得到预测结果中,哪些是正确的那些是错误的
print(classification_report(Y_test, y_pred, target_names=target_names))
print("confusion_matrix:")
#confusion_matrix 是建一个 n x n 的方格,横行和纵行分别表示真实的每一组测试集的标记和测试集标记的差别,通常表示这些测试数据哪些对了,哪些错了
#这个对角线表示了哪些值对了,对角线数字越多,就表示准确率越高
print(confusion_matrix(Y_test, y_pred, labels=range(n_classes)))
结果如下

#将测试的结果进行展示,原先图片应该是谁,结果预测成谁,在此之前,先弄一个通用的图片可视化函数:
import matplotlib.pyplot as plt
def plot_gallery(images, titles, h, w, n_row=3, n_col=4):#row:行数,column:列数
"""Helper function to plot a gallery of portraits"""
plt.figure(figsize=(1.8 * n_col, 2.4 * n_row))
plt.subplots_adjust(bottom=0, left=.01, right=.99, top=.90, hspace=.35)
for i in range(n_row * n_col):
plt.subplot(n_row, n_col, i + 1)#(行数,列数,索引)
plt.imshow(images[i].reshape((h, w)), cmap=plt.cm.gray)
plt.title(titles[i], size=12)
plt.xticks(())
plt.yticks(())
#测试集和特征点可视化:
def title(y_pred, y_test, target_names, i):
pred_name = target_names[y_pred[i]].rsplit(' ', 1)[-1]#1指最多分一个,[-1]指取分之后的最后一个
true_name = target_names[y_test[i]].rsplit(' ', 1)[-1]
return 'predicted: %s\ntrue: %s' % (pred_name, true_name)
prediction_titles = [title(y_pred, Y_test, target_names, i)
for i in range(y_pred.shape[0])]
plot_gallery(X_test, prediction_titles, h, w)
# plot the gallery of the most significative eigenfaces
#下方打印的图像是特征点的,这是一个抽象化的对特征的提取,虽然对人来说它的辨识度低,但对机器来说是很有帮助的。
eigenface_titles = ["eigenface %d" % i for i in range(eigenfaces.shape[0])]
plot_gallery(eigenfaces, eigenface_titles, h, w)
plt.show()
结果如下



网友评论