支持向量机算法小结

用sklearn实现 , 也用自己手动实现了一下, 自己手动实现只能说是展示了算法过程 ,但是效果很差 , 没有找到原因, 希望大神斧正!!!

sklearn实现

from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
import pandas as pd
import numpy as np 

# 构造数据
def create_data():
    iris = load_iris()
    df = pd.DataFrame(iris.data, columns=iris.feature_names)
    df['label'] = iris.target
    df.columns = ['sepal length', 'sepal width', 'petal length', 'petal width', 'label']
    data = np.array(df.iloc[:100, [0, 1, -1]])
    for i in range(len(data)):
        if data[i,-1] == 0:
            data[i,-1] = -1
    # print(data)
    return data[:,:2], data[:,-1]

X, y = create_data()
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.25)

LinearSVC

使用的是线性核函数,k(x,v)=x* v, 只能对线性可分的数据进行分类
from sklearn.svm import LinearSVC
lsvc=LinearSVC(
    C=1.0, # 在模型进行软间隔最大化时引入的惩罚发系数C,需要用交叉验证来找到合适的C,噪音点较多时,C选小一点
    penalty ='l2', # 正则化系数,仅对线性拟合有用, 一般使用l2, 如果需要稀疏系数时, 可以选l1
    dual=True, # 默认是True,即采用对偶形式优化,推荐True
    class_weight=None, # 当数据集各类别的样本数严重不平衡的时候用'balanced',否则默认None
    multi_class='ovr', # 多分类算法, 建议使用默认值
    max_iter=1000, # 最大爹迭代次数, 默认1000
)
lsvc.fit(X_train,y_train)
print('原始问题中的系数:',lsvc.coef_)
print('原始问题中的截距:',lsvc.intercept_)
原始问题中的系数: [[ 1.30179585 -1.96015059]]
原始问题中的截距: [-1.00632957]
score=lsvc.score(X_test,y_test)
print('测试集上的准确率为:',score)
测试集上的准确率为: 1.0

SVC

可选核函数的svm分类器
from sklearn.svm import SVC
svc=SVC(
    C=1.0,
    kernel='rbf', # 默认的是rbf高斯核函数, 可选'linear'线性核函数,'poly'多项式核函数,'sigmoid'sigmoid核函数
    degree=3,
    gamma='auto', # 如果kernel选择的是出linear以外的其他函数,需要通过交叉验证对这三个值进行选择
    coef0=0.0,
    class_weight=None,
    decision_function_shape='ovo', # 可选择ovo和ovr, ovr相对简单,分类效果差,建议使用ovo
    cache_size=200, # 缓存大小会影响训练速度, 当电脑内存大时 ,建议使用500m- 1000m
    max_iter=-1 # 迭代次数默认无限制,直到小于阈值为止
)
svc.fit(X_train,y_train)
print('支持向量的索引',svc.support_)
print('支持向量:',svc.support_vectors_)
print('每个类别的支持向量的数量:',svc.n_support_)
支持向量的索引 [ 5 11 12 19 26 58 59 65  2 21 22 23 43 46 49 50 63 64]
支持向量: [[5.4 3.4]
 [5.7 3.8]
 [5.8 4. ]
 [4.9 3. ]
 [4.8 3. ]
 [4.5 2.3]
 [5.4 3.4]
 [4.8 3. ]
 [5.7 2.9]
 [4.9 2.4]
 [5.7 3. ]
 [5.6 3. ]
 [7.  3.2]
 [6.  3.4]
 [5.1 2.5]
 [5.  2. ]
 [5.  2.3]
 [5.9 3.2]]
每个类别的支持向量的数量: [ 8 10]
score=svc.score(X_test,y_test)
print("准确率为:",score)
准确率为: 1.0

NuSVC

from sklearn.svm import NuSVC
nusvc=NuSVC(
    nu=0.5, # nu代表训练集训练的错误率的上限,或者说支持向量的百分比下限,取值范围为(0,1],默认是0.5.它和惩罚系数C类似,都可以控制惩罚的力度。
    kernel='rbf',
    degree=3,
    gamma='auto', # 如果kernel选择的是出linear以外的其他函数,需要通过交叉验证对这三个值进行选择
    coef0=0.0,
    class_weight=None,
    decision_function_shape='ovo', # 可选择ovo和ovr, ovr相对简单,分类效果差,建议使用ovo
    cache_size=200, # 缓存大小会影响训练速度, 当电脑内存大时 ,建议使用500m- 1000m
    max_iter=-1 # 迭代次数默认无限制,直到小于阈值为止
    
)
nusvc.fit(X_train,y_train)
print('支持向量的索引',nusvc.support_)
#print('支持向量:',nusvc.support_vectors_)
print('每个类别的支持向量的数量:',nusvc.n_support_)
支持向量的索引 [ 4  5  6  8 11 12 14 19 26 28 29 36 37 42 54 58 59 61 65 69  2  3 21 22
 23 24 31 33 34 43 44 45 46 49 50 53 62 63 64 67]
每个类别的支持向量的数量: [20 20]
score=nusvc.score(X_test,y_test)
print("准确率为:",score)
准确率为: 1.0

手动实现

import numpy as np 
from sklearn.datasets import load_iris
from sklearn.model_selection import  train_test_split
import pandas as pd

class SVM(object):

	def __init__(self,max_iterations,kernal='linear'):
		
		self.max_iterations=max_iterations
		self._kernal=kernal

	def _init_params(self,X,Y):

 		self.m=X.shape[0]
 		self.n=X.shape[1]
 		self.X=X
 		self.Y=Y
 		self.b=0.0
 		self.alpha=np.ones(self.m)
 		self.E=[ self._E(i) for i in range(self.m)]
 		self.C=1.0
 		

	def _k(self,xi,xj):
		if self._kernal=='linear':
 			return sum([xi[i]*xj[i] for i in range(self.n)])

	def _g(self,i):
		
		g=0
		for j in range(self.m):
			g+=self.alpha[j]*self.Y[j]*self._k(self.X[j],self.X[i])+self.b 
		return g

	def _E(self,i):

 		E=self._g(i)-self.Y[i]

 		return E

	def _KKT(self,i):
		y_g=self.Y[i]*self._g(i)
		if self.alpha[i]==0:
 			return y_g>1
		elif self.alpha[i]>0 and self.alpha[i]<self.C:
 			return y_g==1
		else:
 			return y_g<1

	def _init_alpha(self):

		index_list=[i for i in range(self.m) if 0<self.alpha[i]<self.C]
		non_index_list=[i for i in range(self.m) if i not in index_list]
		index_list.extend(non_index_list)

		for i in index_list:
			if self._KKT(i):
				continue
			E1=self.E[i]

			if E1>=0:
				j=min(range(self.m),key=lambda x:self.E[x])
			else:
				j=max(range(self.m),key=lambda x:self.E[x])
			return (i,j)

	def _compare(self,alpha2,L,H):
		if alpha2>H:
			return H
		elif alpha2<L:
			return L
		else:
			return alpha2

	def fit(self,features,labels):

		self._init_params(features,labels)

		for iter in range(self.max_iterations):

			i,j=self._init_alpha()

			if self.Y[i]!=self.Y[j]:
				L=max(0,self.alpha[j]-self.alpha[i])
				H=min(self.C,self.C+self.alpha[j]-self.alpha[i])
			elif self.Y[i]==self.Y[j]:
				L=max(0,self.alpha[j]+self.alpha[i]-self.C)
				H=min(self.C,self.alpha[j]+self.alpha[i])
			
			E1=self.E[i]
			E2=self.E[j]

			eta=self._k(self.X[i],self.X[i])+self._k(self.X[j],self.X[j])-2*self._k(self.X[i],self.X[j])
			if eta<=0:
				continue
			
			alpha2_new_unc=self.alpha[j]+self.Y[j]*(E2-E1)/eta
			alpha2_new=self._compare(alpha2_new_unc,L,H)
			
			alpha1_new=self.alpha[i]+self.Y[i]*self.Y[j]*(self.alpha[j]-alpha2_new)

			b1=-E1 - self.Y[i]*self._k(self.X[i],self.X[i])*(alpha1_new-self.alpha[i])-self.Y[j]*self._k(self.X[j],self.X[i])*(alpha2_new-self.alpha[j])+self.b
	
			b2=-E2 - self.Y[i]*self._k(self.X[i],self.X[j])*(alpha1_new-self.alpha[i])-self.Y[j]*self._k(self.X[j],self.X[j])*(alpha2_new-self.alpha[j])+self.b

			if alpha1_new>0 and alpha1_new<self.C:
				b_new=b1

			elif alpha2_new>0 and alpha2_new<self.C:
				b_new=b2
			else:
				b_new=(b1+b2)/2

			self.alpha[i]=alpha1_new
			self.alpha[j]=alpha2_new
			self.b=b_new

			self.E[i]=self.E[i]
			self.E[j]=self.E[j]

		return 'train done!'

	def predict(self,data):
		result=0
		for i in range(self.m):
			result+=self.alpha[i]*self.Y[i]*self._k(self.X[i],data)+self.b
		return 1 if result>0 else -1
		
	def score(self,data,labels):
		Y_pred=[]
		for i in range(len(data)):
			y_pred=self.predict(data[i])
			Y_pred.append(y_pred)
		Y_pred=np.array(Y_pred)
		score=1-len(labels[labels+Y_pred==0])/len(labels)
		return score
X, y = create_data()
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.25)

max_iterations=200
svm=SVM(max_iterations)
svm.fit(X_train,y_train)
score=svm.score(X_test,y_test)
print(score)
0.76

完整代码:https://github.com/TaoistNie/The-road-to-ML/tree/master/SVM

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值