文章目录
1. SVM(Support Vector Machines)原理
SVM(support vector machine)简单的说是一个分类器,并且是二分类器。
对一个分类问题,如果数据是线性可分的,也就是用一条直线就可以将两种类别分开的时候,我们只要将直线的位置放在让两边距离直线的距离最大化的位置即可,寻找这个最大间隔的过程,就叫做最优化。
关于SVM的公式推导,已有很多详细的推导(见参考博客[1])在这里不多赘述,只附上之前自己学习时的几点笔记。
这里简单说一下核函数:现实中数据通常是线性不可分的,也就是找不到一条直线将两种类别很好的分类。这个时候,我们就需要用超平面代替直线将数据进行分类,这时需要用到核函数(kernel)来应对高维空间的复杂计算。常用的核函数有以下几种:
线性核函数
κ
(
x
,
x
i
)
=
x
⋅
x
i
κ(x,xi)=x⋅xi
κ(x,xi)=x⋅xi
κ
(
x
,
x
i
)
=
x
⋅
x
i
κ(x,xi)=x⋅xi
κ(x,xi)=x⋅xi
线性核,主要用于线性可分的情况,我们可以看到特征空间到输入空间的维度是一样的,其参数少速度快,对于线性可分数据,其分类效果很理想,因此我们通常首先尝试用线性核函数来做分类,看看效果如何,如果不行再换别的
多项式核函数
κ
(
x
,
x
i
)
=
(
(
x
⋅
x
i
)
+
1
)
d
κ(x,xi)=((x⋅xi)+1)d
κ(x,xi)=((x⋅xi)+1)d
多项式核函数可以实现将低维的输入空间映射到高纬的特征空间,但是多项式核函数的参数多,当多项式的阶数比较高的时候,核矩阵的元素值将趋于无穷大或者无穷小,计算复杂度会大到无法计算。
高斯(RBF)核函数
κ
(
x
,
x
i
)
=
e
x
p
(
−
∣
∣
x
−
x
i
∣
∣
2
δ
2
)
κ(x,xi)=exp(\frac{−||x−xi||2}{δ2})
κ(x,xi)=exp(δ2−∣∣x−xi∣∣2)
高斯径向基函数是一种局部性强的核函数,其可以将一个样本映射到一个更高维的空间内,该核函数是应用最广的一个,无论大样本还是小样本都有比较好的性能,而且其相对于多项式核函数参数要少,因此大多数情况下在不知道用什么核函数的时候,优先使用高斯核函数。
sigmoid核函数
κ
(
x
,
x
i
)
=
t
a
n
h
(
η
<
x
,
x
i
>
+
θ
)
κ(x,xi)=tanh(η<x,xi>+θ)
κ(x,xi)=tanh(η<x,xi>+θ)
采用sigmoid核函数,支持向量机实现的就是一种多层神经网络。
在选用核函数的时候,如果我们对我们的数据有一定的先验知识,就利用先验来选择符合数据分布的核函数;如果不知道的话,通常使用交叉验证的方法,来试用不同的核函数,误差最下的即为效果最好的核函数,或者也可以将多个核函数结合起来,形成混合核函数。在吴恩达的课上,也曾经给出过一系列的选择核函数的方法:
如果特征的数量大到和样本数量差不多,则选用LR或者线性核的SVM;
如果特征的数量小,样本的数量正常,则选用SVM+高斯核函数;
如果特征的数量小,而样本的数量很大,则需要手工添加一些特征从而变成第一种情况。
2. SVM应用场景
(1)数据不是线性可分的,需要使用非线性核的svm(虽然logistic regression也可以用不同的核,但由于实际原因(什么?)还是用svm比较好);
(2) 另一个场景是特征空间维度很高,例如svm在文本分类中的效果较好。
3. SVM优缺点
优点
1.可以解决高维问题,即大型特征空间;
2.能够处理非线性特征的相互作用;
3.无需依赖整个数据;
4.可以提高泛化能力;
缺点
1.当观测样本很多时,效率并不是很高;
2.一个可行的解决办法是模仿随机森林,对数据分解,训练多个模型,然后求平均,时间复杂度降低p倍,分多少份,降多少倍
3.对非线性问题没有通用解决方案,有时候很难找到一个合适的核函数;
4.对缺失数据敏感;
4. SVM sklearn 参数学习
sklearn中用于分类的SVM模型为SVC,另外还提供了用于预测的回归模型SVR。两种模型调用时的参数设置类似,这里主要说一下SVC的参数设置。
SVC()参数:
C : 惩罚系数
类型:float, optional (default=1.0)
kernel : 核函数
类型:string, optional (default=‘rbf’)
可选参数有:
‘linear’:线性核函数
‘poly’:多项式核函数
‘rbf’:径像核函数/高斯核
‘sigmod’:sigmod核函数
‘precomputed’:核矩阵
degree : 只对多项式核函数有用,是指多项式核函数的阶数n
类型:int, optional (default=3)
gamma : 核函数系数,只对‘rbf’,‘poly’,‘sigmod’有效。
类型:float, optional (default=‘auto’)
coef0 : 核函数中的独立项,只有对‘poly’和‘sigmod’核函数有用,是指其中的参数c
类型:float, optional (default=0.0)
probability : 是否启用概率估计。 这必须在调用fit()之前启用,并且fit()方法速度变慢。
类型:boolean, optional (default=False)
shrinking : 是否采用启发式收缩方式
boolean, optional (default=True)
tol : svm停止训练的误差精度
类型:float, optional (default=1e-3)
cache_size : 指定训练所需要的内存,以MB为单位,默认为200MB。
类型:float, optional
class_weight : 给每个类别分别设置不同的惩罚参数C,如果没有给,则会给所有类别都给C=1,即前面参数指出的参数C.
如果给定参数‘balance’,则使用y的值自动调整与输入数据中的类频率成反比的权重。
类型:{dict, ‘balanced’}, optional
verbose : 是否启用详细输出。 此设置利用libsvm中的每个进程运行时设置,如果启用,可能无法在多线程上下文中正常工作。
类型:bool, default: False
max_iter : 最大迭代次数,如果为-1,表示不限制
类型:int, optional (default=-1)
random_state : 伪随机数发生器的种子,在混洗数据时用于概率估计。
类型:int, RandomState instance or None, optional (default=None)
5. 利用SVM模型结合 Tf-idf 算法进行文本分类
这里利用SVM模型结合 Tf-idf 算法对THUCNEWS数据集进行了分类
from sklearn.metrics import confusion_matrix
from sklearn.metrics import classification_report
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.preprocessing import LabelEncoder
from cnew_deal.pre_data import *
from sklearn.svm import SVC
import sklearn.naive_bayes as nb
train_data = pd.read_csv('G:/PycharmCode/NLP/cnews/cnews.train.txt', sep='\t', names=['label', 'content'])
test_data = pd.read_csv('G:/PycharmCode/NLP/cnews/cnews.test.txt', sep='\t', names=['label', 'content'])
label_list = []
for i in train_data['label']:
label_list.append(i)
with open('train_content.pickle', 'rb') as f:
train_content = pk.load(f)
with open('test_content.pickle', 'rb') as f:
test_content = pk.load(f)
labelEncoder = LabelEncoder()
train_y = labelEncoder.fit_transform(label_list)
print(len(train_y))
vectorizer = TfidfVectorizer()
x_train = vectorizer.fit_transform(train_content)
x_test = vectorizer.transform(test_content)
y_train = train_y
model = SVC(C=0.5)
model.fit(x_train, y_train)
print('--------------------训练完成-----------------------')
test_label_list = []
for i in test_data['label']:
test_label_list.append(i)
y_test = labelEncoder.transform(test_label_list)
print(len(y_test))
predic = model.predict(x_test)
print(len(predic))
print("classification report on test set for classifier:")
print(classification_report(y_test, predic))
print(model.score(x_test, predic))
print(confusion_matrix(y_test, predic))
呃…经过漫长的等待…这个结果,感觉有点过分了啊…先贴图,我再去改改
参考
[1]Python3《机器学习实战》学习笔记(八):支持向量机原理篇之手撕线性SVM - CSDN博客 (https://blog.csdn.net/c406495762/article/details/78072313)
[2]svm常用核函数 - CSDN博客(https://blog.csdn.net/batuwuhanpei/article/details/52354822 )