线性不可分SVM(SMO算法)
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from sklearn import preprocessing
from sklearn.model_selection import train_test_split
from sklearn.svm import SVC
from sklearn.metrics import classification_report
import warnings
warnings.filterwarnings('ignore')
data = pd.read_csv('data.csv',encoding='utf8',header=None)
arr = data.values
encoder = preprocessing.LabelEncoder()
labels = encoder.fit_transform(arr[:,1])
for label,num in enumerate(encoder.classes_):
print(label,'-->',num)
arr[:,1] = labels
x,y = arr[:,0:-1],arr[:,-1]
nx = preprocessing.StandardScaler().fit_transform(x)
x_train,x_test,y_train,y_test = train_test_split(nx.astype(float),y.astype(float),test_size=0.2,random_state=1)
(n,m) = x_train.shape
def func(x,y,choice):
if choice == 'rbf':
r = 0.5
result = np.exp(-r*sum((x-y)**2))
if choice == 'poly':
p = 2
result = (np.dot(x.T,y)+1)**p
return result
gram = np.zeros((n,n))
for i in range(n):
for j in range(n):
gram[i,j] = func(x_train[i],x_train[j],'rbf')
a = np.zeros(n)
b = 0
C = 1
p = np.zeros(n)
maxgen = 100
def v1(a,y,gram):
yg = np.dot((a*y).T,gram)
e = (yg-1)**2
e1,e2,e3 = e,e.copy(),e.copy()
e1[(a>0)|(yg>=1)] = 0
e2[(a==0)|(a==C)|(yg==1)] = 0
e3[(a<C)|(yg<=1)] = 0
s = e1+e2+e3
index = np.argmax(s)
return index
def v2(v1,n):
index = np.random.randint(n)
while v1 == index:
index = np.random.randint(n)
return index
for t in range(maxgen):
i1 = v1(a,y_train,gram)
i2 = v2(i1,n)
old_a1,old_a2 = a[i1],a[i2]
old_y1,old_y2 = y_train[i1],y_train[i2]
if old_y1 == old_y2:
L = max(0,old_a2+old_a1-C)
H = min(C,old_a2+old_a1)
else:
L = max(0,old_a2-old_a1)
H = min(C,old_a2-old_a1+C)
E1 = np.dot((a*y_train).T,gram[:,i1])+b - y_train[i1]
E2 = np.dot((a*y_train).T,gram[:,i2])+b - y_train[i2]
g = gram[i1,i1]+gram[i2,i2]-2*gram[i1,i2]
tmp_a2 = old_a2 + y_train[i2]*(E1-E2)/g
if tmp_a2>H:
a[i2] = H
if tmp_a2 >=L and tmp_a2<=H:
a[i2] = tmp_a2
if tmp_a2<L:
a[i2] = L
deta_a2 = a[i2]-old_a2
a[i1] = old_a1-old_y1*old_y2*deta_a2
deta_a1 = a[i1]-old_a1
dw = (y_train[i1]*deta_a1,y_train[i2]*deta_a2)
b1 = -E1-y_train[i1]*gram[i1,i1]*deta_a1-y_train[i2]*gram[i1,i2]*deta_a2
b2 = -E2-y_train[i1]*gram[i1,i2]*deta_a1-y_train[i2]*gram[i2,i2]*deta_a2
db = (b1+b2)/2
p = p+dw[0]*gram[i1].T+dw[1]*gram[i2].T+db
w = np.dot(x_train.T,(a*y_train))
index = np.where((a>0)&(a<C))[0][0]
b = y_train[index]-np.dot((y_train*a).T,gram[:,index])
predict_train = np.sign(np.dot(x_train,w)+b)
train_acc = len(y_train[predict_train==y_train])/len(y_train)
print('Train acc = ',train_acc)
print(classification_report(y_train,predict_train))
predict_test = np.sign(np.dot(x_test,w)+b)
test_acc = len(y_test[predict_test==y_test])/len(y_test)
print('Test acc = ',test_acc)
print(classification_report(y_test,predict_test))
print('------sklearn-SVC------')
clf = SVC(C=1.0,kernel='rbf')
clf.fit(x_train,y_train.astype(int))
predict_train = clf.predict(x_train)
train_acc = len(y_train[predict_train==y_train])/len(y_train)
predict_test = clf.predict(x_test)
test_acc = len(y_test[predict_test==y_test])/len(y_test)
print('Train acc:',train_acc,'\n',classification_report(y_train.astype(int),predict_train))
print('Test acc:',test_acc,'\n',classification_report(y_test.astype(int),predict_test))