1. 소개
win10, 파이썬 3.6, 노트북
참고:
[머신러닝 실습] Support Vector Machine----분류 라이브러리 및 단순 학습 mnist
https://blog.csdn.net/u013597931/article/details/80076058
SVM 연구 노트(2)----필기 숫자 인식
https://blog.csdn.net/chunxiao2008/article/details/50448154
2. SVM 모듈에 대한 자세한 설명
기본 이론 -------알고리즘 라이브러리------속성---------방법
기본 이론:
- 기본 아이디어는 분류에 최대 간격을 사용하는 것입니다.
- 비선형 문제를 해결하기 위해 특징 벡터를 커널 함수를 통해 고차원 공간에 매핑함으로써 선형 분리가 가능해 지지만 연산은 저차원 공간에서 수행됩니다.
- 데이터에 노이즈가 있을 수 있다는 점을 고려하여 여유 변수도 도입되었습니다.
다음 라이브러리는 sklearn.svm 모듈에서 제공됩니다.
이는 대략적으로 다음 범주로 나뉩니다(svm_l1_min_c가 페널티 매개변수 C의 최저 경계를 반환한다는 점 제외).
분류 라이브러리의 주요 매개변수:
다른 매개변수에 대한 소개를 보려면 공식 라이브러리(
http://scikit-learn.org/stable/modules/classes.html#module-sklearn.svm
)를 보거나 이 블로거의 요약을 살펴보세요(요약은 매우 좋습니다). :
http://www.cnblogs.com/pinard/p/6117515.html
속성:
방법:
훈련을 위한 fit(), 점수 매기기를 위한 Score(), 새로운 샘플 예측을 위한 예측(), 샘플 지점에서 분리 초평면까지의 거리를 계산하는 Decision_function() 등을 포함하여 일반 모델과 동일합니다.
3. SVM 분류의 간단한 구현
분류에는 세 가지 다른 SVC가 사용되었습니다.
- SVC: svm.SVC(커널='선형')
- 선형SVC: svm.LinearSVC()
- NuSVC: svm.NuSVC(커널='선형'
알 수있는 바와 같이:
- LinearSVC 훈련으로 얻은 분리 초평면은 SVC의 것과 다릅니다.
- NuSVC 모델의 서포트 벡터는 샘플 수의 절반을 차지하며, nu=0.01인 경우 SVC와 동일하므로 학습 오차나 서포트 벡터의 백분율에 대한 요구 사항이 있는 경우 NuSVC를 선택할 수 있습니다.
1. 데이터 세트
##用于可视化图表
import matplotlib.pyplot as plt
##用于做科学计算
import numpy as np
##用于做数据分析
import pandas as pd
##用于加载数据或生成数据等
from sklearn import datasets
##加载svm模型
from sklearn import svm
##随机生成一组特征数量为2,样本数量为80的数据集
X, y = datasets.make_blobs(n_samples=80, n_features=2, centers=2, random_state=3)
fig=plt.figure(figsize=(10,8))
plt.xlim(-8,4) # 设置x轴刻度范围
plt.ylim(-5,8) # 设置y轴刻度范围
plt.scatter(X[:, 0], X[:, 1], c=y, s=30)
plt.show()
2、 svm.SVC(kernel='선형')
##加载svm的svc模型,选择线性核linear
model_svc=svm.SVC(kernel='linear')
model_svc.fit(X,y)
print("各类的支持向量在训练样本中的索引",model_svc.support_)
print("各类所有的支持向量:\n",model_svc.support_vectors_)
print("各类各有多少个支持向量",model_svc.n_support_)
print("各特征系数",model_svc.coef_)
print("截距",model_svc.intercept_)
print("各样本点到分离超平面的距离:\n",model_svc.decision_function(X))
fig=plt.figure(figsize=(10,8))
plt.xlim(-8,4) # 设置x轴刻度范围
plt.ylim(-5,8) # 设置y轴刻度范围
##显示分离超平面
w1=model_svc.coef_[:,0]
w2=model_svc.coef_[:,1]
b=model_svc.intercept_
x1=np.linspace(-8,6,2)
x2=(w1*x1+b)/(-1*w2)
x2_up=(w1*x1+b+1)/(-1*w2)
x2_down=(w1*x1+b-1)/(-1*w2)
plt.plot(x1,x2,'k-',linewidth=0.8)
plt.plot(x1,x2_up,'k--',linewidth=0.8)
plt.plot(x1,x2_down,'k--',linewidth=0.8)
##显示样本点和支持向量
plt.scatter(X[:, 0], X[:, 1], c=y,s=30)
plt.scatter(model_svc.support_vectors_[:, 0], model_svc.support_vectors_[:, 1],s=80,c='',edgecolors='b')
plt.show()
各类的支持向量在训练样本中的索引 [ 3 77 63]
各类所有的支持向量:
[[ 0.21219196 1.74387328]
[-1.23229972 3.89519459]
[-2.94843418 0.3655385 ]]
各类各有多少个支持向量 [2 1]
各特征系数 [[-0.48951758 -0.32852537]]
截距 [-0.32333516]
各样本点到分离超平面的距离:
[-1.96224709 1.96992652 1.61830594 -1.00011347 -3.03968748 -1.91355576
-3.20222196 1.07605938 1.39390527 1.19794817 -3.09852679 -2.99356435
1.83058651 2.46025289 1.84454041 -1.98203511 1.18207352 -2.21362739
-1.93596757 1.5062249 -3.13955464 -1.41328098 2.11163776 -2.0100733
1.23402066 -1.3997197 1.42460256 1.9676612 1.10767531 1.64961948
1.95638419 1.51193805 -1.2642258 2.06733658 1.99862207 1.49307471
-1.44123444 -1.54063897 2.21232256 3.39921728 1.08180429 1.72267793
-3.1813601 1.61914905 1.59985133 -1.70286262 -1.94181226 1.59417872
2.15236394 -2.64727844 -2.54908967 -1.45290411 -2.30745878 -2.58497233
2.2307059 -2.6951711 -2.96443813 -1.73637146 2.20696118 -1.77028229
-2.67467925 -1.60612382 2.59439321 0.99988654 -1.59570877 1.53629311
-2.69403494 1.44783106 -2.07984685 -1.3734872 1.09058746 1.60125344
1.76284029 -1.83576229 -1.90749178 -2.44163699 2.01923035 -0.99977302
2.01835361 -1.9910022 ]
3、svm.LinearSVC()
##加载svm的LinearSVC模型
model_svc=svm.LinearSVC()
model_svc.fit(X,y)
print("各特征系数",model_svc.coef_)
print("截距",model_svc.intercept_)
print("各样本点到分离超平面的距离:\n",model_svc.decision_function(X))
fig=plt.figure(figsize=(10,8))
plt.xlim(-8,4) # 设置x轴刻度范围
plt.ylim(-5,8) # 设置y轴刻度范围
##显示分离超平面
w1=model_svc.coef_[:,0]
w2=model_svc.coef_[:,1]
b=model_svc.intercept_
x1=np.linspace(-8,6,2)
x2=(w1*x1+b)/(-1*w2)
x2_up=(w1*x1+b+1)/(-1*w2)
x2_down=(w1*x1+b-1)/(-1*w2)
plt.plot(x1,x2,'k-',linewidth=0.8)
plt.plot(x1,x2_up,'k--',linewidth=0.8)
plt.plot(x1,x2_down,'k--',linewidth=0.8)
##显示样本点和支持向量
plt.scatter(X[:, 0], X[:, 1], c=y,s=30)
plt.show()
各特征系数 [[-0.43861872 -0.34666587]]
截距 [-0.17687917]
各样本点到分离超平面的距离:
[-1.93588632 1.87233349 1.51364971 -0.87449188 -2.92992153 -1.76381697
-3.07749808 1.04025334 1.29833361 1.11381917 -2.93977862 -2.79956624
1.71631792 2.39358778 1.73195783 -1.92786837 1.09573885 -2.04452242
-1.82100181 1.42159955 -2.9877508 -1.29033632 2.02059401 -1.88099763
1.19084793 -1.30551704 1.40518201 1.87446768 0.99415791 1.64725845
1.9009514 1.43403277 -1.1375335 1.94926655 1.87258846 1.44713253
-1.30509778 -1.4745769 2.12237058 3.19811264 1.04509393 1.58901995
-3.04486552 1.48196178 1.52057507 -1.59990501 -1.8120006 1.48499025
2.06828345 -2.51227207 -2.3304399 -1.36943056 -2.11483449 -2.43410562
2.09715535 -2.51291992 -2.80568943 -1.64868248 2.14688497 -1.69265193
-2.59427138 -1.57782921 2.51736177 0.98963954 -1.54715292 1.50308216
-2.61135208 1.38378795 -1.94731015 -1.30279915 0.96583083 1.58100889
1.64279966 -1.796035 -1.8219179 -2.28425194 1.91261392 -0.98670045
1.90619623 -1.79154379]
4、 svm.NuSVC(커널='선형')
##加载svm的NuSVC模型,nu为默认值0.5
model_svc=svm.NuSVC(kernel='linear')
#model_svc=svm.NuSVC(kernel='linear',nu=0.01)
model_svc.fit(X,y)
print("各类的支持向量在训练样本中的索引",model_svc.support_)
print("各类各有多少个支持向量",model_svc.n_support_)
print("各特征系数",model_svc.coef_)
print("截距",model_svc.intercept_)
print("各样本点到分离超平面的距离:\n",model_svc.decision_function(X))
fig=plt.figure(figsize=(10,8))
plt.xlim(-8,4) # 设置x轴刻度范围
plt.ylim(-5,8) # 设置y轴刻度范围
##显示分离超平面
w1=model_svc.coef_[:,0]
w2=model_svc.coef_[:,1]
b=model_svc.intercept_
x1=np.linspace(-8,6,2)
x2=(w1*x1+b)/(-1*w2)
x2_up=(w1*x1+b+1)/(-1*w2)
x2_down=(w1*x1+b-1)/(-1*w2)
plt.plot(x1,x2,'k-',linewidth=0.8)
plt.plot(x1,x2_up,'k--',linewidth=0.8)
plt.plot(x1,x2_down,'k--',linewidth=0.8)
##显示样本点和支持向量
plt.scatter(X[:, 0], X[:, 1], c=y,s=30)
plt.scatter(model_svc.support_vectors_[:, 0], model_svc.support_vectors_[:, 1],s=80,c='',edgecolors='b')
plt.show()
各类的支持向量在训练样本中的索引 [ 0 3 5 18 21 25 32 36 37 45 46 51 57 59 61 64 69 73 74 77 79 2 7 8
9 16 19 24 26 28 31 35 40 43 44 47 63 65 67 70 71]
各类各有多少个支持向量 [21 20]
各特征系数 [[-0.26852918 -0.18506518]]
截距 [-0.07402223]
各样本点到分离超平面的距离:
[-1.00000001 1.18344728 0.98651753 -0.45373219 -1.59369374 -0.9613798
-1.68303355 0.69021961 0.86209936 0.75377706 -1.62199582 -1.56013705
1.10412131 1.46001562 1.11206673 -1.00846728 0.74471129 -1.12708414
-0.97711454 0.92581127 -1.64554153 -0.68461074 1.26315788 -1.017172
0.77771057 -0.67970603 0.886296 1.18259074 0.70066156 1.01348247
1.17979741 0.9296235 -0.60106054 1.23592282 1.1968279 0.92205787
-0.6989911 -0.76097669 1.31946142 1.97167963 0.69334256 1.04208873
-1.67029696 0.98397159 0.97856961 -0.84810873 -0.97900041 0.97262943
1.28653695 -1.3723103 -1.30974513 -0.7103885 -1.17727995 -1.33606029
1.32568017 -1.39466306 -1.54714741 -0.86822923 1.31923904 -0.88809099
-1.3926683 -0.80103249 1.53393157 0.65006995 -0.79334001 0.94736295
-1.4032617 0.89512436 -1.0557987 -0.66724352 0.69008091 0.9848262
1.0657701 -0.92815667 -0.96394481 -1.25544599 1.21013198 -0.46397868
1.20912877 -1. ]
4. 최소 데이터 세트
미니스트 공식 홈페이지: http://yann.lecun.com/exdb/mnist/
공식 홈페이지에 있는 데이터 세트는 gz 형식인데, Windows에서는 gz 형식을 압축 해제하는 것이 더 번거롭습니다.
따라서 훈련에는 두 가지 데이터 세트가 사용됩니다.
- 첫 번째는 압축이 풀린 공식 웹사이트 데이터 세트입니다.
- 하나는 mnist.pkl.gz이며 비교합니다.
1、mnist.pkl.gz
참고: https://blog.csdn.net/chunxiao2008/article/details/50448154
scikit-learn 라이브러리에서 SVM을 직접 호출하여 기본 매개변수와 손으로 쓴 숫자 1,000장의 그림을 사용하여 정확하게 판단된 그림의 개수는 9,435장에 달합니다.
위 코드는 검증 세트로 검증되지 않습니다. 왜냐하면 이 예에서는 동일한 것을 판단하기 위해 테스트 세트와 검증 세트를 사용하고, 이를 다시 검증하기 위해 일부러 검증 세트를 사용할 필요가 없기 때문입니다.
데이터 가져오기:
# import cPickle
import _pickle as cPickle
import gzip
import numpy as np
from sklearn import svm
import time
def load_data():
"""
返回包含训练数据、验证数据、测试数据的元组的模式识别数据
训练数据包含50,000张图片,测试数据和验证数据都只包含10,000张图片
"""
f = gzip.open('MNIST_data/mnist.pkl.gz', 'rb')
# training_data, validation_data, test_data = cPickle.load(f)
training_data, validation_data, test_data = cPickle.load(f,encoding='bytes')
f.close()
return (training_data, validation_data, test_data)
분류:
# 使用SVM分类器,从MNIST数据集中进行手写数字识别的分类程序
def svm_baseline():
#print time.strftime('%Y-%m-%d %H:%M:%S')
print(time.strftime('%Y-%m-%d %H:%M:%S'))
training_data, validation_data, test_data = load_data()
# 传递训练模型的参数,这里用默认的参数
clf = svm.SVC()
# clf = svm.SVC(C=8.0, kernel='rbf', gamma=0.00,cache_size=8000,probability=False)
# 进行模型训练
clf.fit(training_data[0], training_data[1])
# test
# 测试集测试预测结果
predictions = [int(a) for a in clf.predict(test_data[0])]
num_correct = sum(int(a == y) for a, y in zip(predictions, test_data[1]))
print("%s of %s test values correct." % (num_correct, len(test_data[1])))
print(time.strftime('%Y-%m-%d %H:%M:%S'))
if __name__ == "__main__":
svm_baseline()
결과:
2018-12-17 15:16:57
9435 of 10000 test values correct.
2018-12-17 15:29:36
2、t10k-images.idx3-ubyte等
데이터:
import numpy as np
import struct
import matplotlib.pyplot as plt
import os
##加载svm模型
from sklearn import svm
###用于做数据预处理
from sklearn import preprocessing
import time
path='MNIST_data'
def load_mnist_train(path, kind='train'):
labels_path = os.path.join(path,'%s-labels.idx1-ubyte'% kind)
images_path = os.path.join(path,'%s-images.idx3-ubyte'% kind)
with open(labels_path, 'rb') as lbpath:
magic, n = struct.unpack('>II',lbpath.read(8))
labels = np.fromfile(lbpath,dtype=np.uint8)
with open(images_path, 'rb') as imgpath:
magic, num, rows, cols = struct.unpack('>IIII',imgpath.read(16))
images = np.fromfile(imgpath,dtype=np.uint8).reshape(len(labels), 784)
return images, labels
def load_mnist_test(path, kind='t10k'):
labels_path = os.path.join(path,'%s-labels.idx1-ubyte'% kind)
images_path = os.path.join(path,'%s-images.idx3-ubyte'% kind)
with open(labels_path, 'rb') as lbpath:
magic, n = struct.unpack('>II',lbpath.read(8))
labels = np.fromfile(lbpath,dtype=np.uint8)
with open(images_path, 'rb') as imgpath:
magic, num, rows, cols = struct.unpack('>IIII',imgpath.read(16))
images = np.fromfile(imgpath,dtype=np.uint8).reshape(len(labels), 784)
return images, labels
train_images,train_labels=load_mnist_train(path)
test_images,test_labels=load_mnist_test(path)
분류:
# 标准化
X=preprocessing.StandardScaler().fit_transform(train_images)
X_train=X[0:60000]
y_train=train_labels[0:60000]
# 模型训练
print(time.strftime('%Y-%m-%d %H:%M:%S'))
model_svc = svm.SVC()
model_svc.fit(X_train,y_train)
print(time.strftime('%Y-%m-%d %H:%M:%S'))
# 评分并预测
x=preprocessing.StandardScaler().fit_transform(test_images)
x_test=x[0:10000]
y_pred=test_labels[0:10000]
print(model_svc.score(x_test,y_pred))
y=model_svc.predict(x_test)
결과:
2018-12-17 17:20:00
2018-12-17 17:30:53
0.9657
요약하다:
두 개의 데이터 세트를 사용하면 실행 시간이 10분 이상이고 출력 결과에 큰 오류가 있어 매개변수 조정을 통해 조정할 수 있음을 알 수 있습니다.
중요한 매개변수:
- C: 부동 소수점 유형, 선택 사항(기본값=1.0). 오류항에 대한 페널티 매개변수 C
- 커널: 문자 유형, 선택 사항(기본값='rbf'). 커널 함수 유형을 지정합니다. '선형', '폴리', 'rbf', '시그모이드' 등만 가능합니다.
- 정도 : 정수, 선택 사항(기본값=3). 다항식 커널 함수('poly')를 사용할 때, 다른 커널 함수를 사용할 때 다항식 커널 함수의 매개변수 d를 무시할 수 있습니다.
- 감마 : 부동 소수점 유형, 선택 사항(기본값=0.0). 'rbf', 'poly' 및 'sigmoid' 커널 함수의 계수입니다. 감마가 0이면 피처 차원의 역수 값이 실제로 계산에 사용됩니다. 즉, 특징이 100차원이면 실제 감마는 1/100입니다.
- oef0: 부동 소수점 유형, 선택 사항(기본값=0.0). 커널 함수의 독립 용어는 '폴리' 및 '시그모이드' 커널에만 의미가 있습니다.
머신러닝 전문가인 Andrew Ng는 SVM 분류 알고리즘과 관련하여 항상 가우스 커널 함수를 사용해 왔으며 기본적으로 다른 커널 함수는 사용한 적이 없다고 말했습니다. 이 커널 함수가 가장 널리 사용되는 것을 볼 수 있습니다.
매핑을 위해 가우스 커널을 사용할 때 감마 매개변수를 매우 작게 선택하면 고차 특성에 대한 가중치가 실제로 매우 빠르게 감소하므로 실제로 (수치적으로 근사된) 저차원 부분공간과 동일합니다. 역으로 과거에는 감마를 매우 크게 선택하면 모든 데이터가 선형 분리 가능하도록 매핑될 수 있었습니다. 이는 매우 심각한 과잉 맞춤 문제로 쉽게 이어질 수 있습니다.
C 매개변수는 가장 큰 마진을 가진 초평면을 찾는 것과 "데이터 포인트의 최소 편차 보장" 사이의 가중치입니다. C가 클수록 모델이 허용하는 편차는 작아집니다.
동일한 C의 경우 감마가 클수록 분류 경계가 샘플에 더 가까워집니다. 동일한 감마에 대해 C가 클수록 분류가 더 엄격해집니다.
감마가 너무 크면 C가 아무리 커도 과적합을 방지할 수 없습니다.
감마가 작으면 분류 경계는 매우 선형적입니다.
중간 값을 취하면 좋은 모델의 감마와 C는 대략 대각선 위치에 분포됩니다.
또한 감마가 중간 값을 취하는 경우 C 값이 매우 커질 수 있다는 점에 유의해야 합니다.