sklearn中LinearSVC源码解析

工作过程中,很多时候为了快速验证一个可能可行的思路,先上来用一下现成的模型跑一跑看一下结果,前一段时间在做浏览器网址分类,把一个URL进行特征抽取,差不多一个URL抽出了20-30个特征,第一个想法就是先用多分类SVM看一下效果,为了快速验证思路,直接用python中sklearn库的LinearSVC类进行训练的。分析团队只给我标注了10000个样本,所以准确率最高只有86%。

 

sklearn中的LinearSVC实质上类似于SVC模型中kernel参数为linear时对应的模型。查看源码的时候,注释里写了一句“but implemented in terms of liblinear rather than libsvm”,这里说一下liblinear和libsvm这两个工具包。libsvm在数据量较小的时候比较适用,当数据量较大的时候,liblinear是效果与libsvm的效果较差基本不到1个百分点,但是速度要远远快于libsvm,liblinear的主要的好处就是速度快,尤其是对于稀疏的特征。对于文本分类这类问题,样本数和特征数都很大,问题的维度大,到万的量级,优先使用线性核而非高斯核,因此,使用liblinear实现的LinearSVC是比较好的选择。此外,对于样本很有限,特征维度很高的情况下,用非线性分类方法得到的kernel map通常是不准的,很可能错分类别空间,效果很差,没必要用。其实退一步讲,对于线性问题来说,liblinear和libsvm二者的目标函数也是不一样的。liblinear的目标函数为,而libsvm的目标函数为,外加两个约束,貌似如果二者采用同样的目标函数的话,性能应该是差不多。除了速度上的优势外,LinearSVC还能更灵活地选择正则项和损失函数。默认的正则项是L2范数,损失函数默认为平方合页损失(平方合页损失就是合页损失函数的平方值),C值为1(如果人为传进去的参数值小于0,会raise一个error,提示必须大于0才行),最多迭代1000次。在进行多分类时,采用的是one - vs - rest这种策略,对应的参数为multi_class,默认值为ovr,即one - vs - rest的缩写。

在训练模型的时候,使用一个随机数生成器随机选择特征训练,因此对于同样的输入数据来说,结果会有些许的差异。训练模型时的接口函数为fit函数,该函数接收两个参数:训练集的X和训练集的y,格式均为array-like。查看训练过程的源码,把参数值都传入liblinear中进行训练。

回溯liblinear的接口函数_fit_liblinear时发现,这个函数在svm和lr的多分类时都有用到,默认的损失函数是logistic regression(在linearsvc中更改了这个默认参数)。_fit_liblinear这个函数首先是先把类别进行编码处理,对于有n_classes个类别的数据集,将类别成0 ~ n_classes-1之间的数字,然后再对类别进行加权,各个类别的权重为n_samples / (n_classes * np.bincount(y)),返回一个vector,vector中第i维向量表示第i类的权重。除了类别权重之外,还有样本权重,在_fit_liblinear这个函数其实是有sample_weight这个参数的,默认为None,表示所有样本权重一样,若不为None的话,需要传进来一个array。体现到多分类这个问题上时,multi_calss这个参数主要应用在_get_liblinear_solver_type这个函数中,这个函数的主要作用是确定solver(solver用来对对偶问题进行求解)的magic number。magic number的确定由以下4个参数决定:multi_class、penalty、loss和dual。个人理解这个magic number的含义是,对所有可能的组合都标一个号,比如说,损失为合页损失函数,使用对偶求解、L2正则和ovr多分类标号为1,损失为平方合页损失,使用对偶求解、L2正则和ovr多分类标号为2...这个函数最终返回的是一个solver_type值,也就是那个标号,然后再传给_fit_liblinear的主体训练函数train_wrap,进行常规线性核SVM的训练。

 

使用这个库实践的时候蛮简单的,引入方式如下:

from sklearn.svm import LinearSVC

然后创建类实例,训练,预测,代码如下:

model = LinearSVC()
X_train, X_test, y_train, y_test, indices_train, indices_test = train_test_split(features, labels, df.index, test_size=0.33, random_state=0)
model.fit(X_train, y_train)
y_pred = model.predict(X_test)

查看混淆矩阵:

conf_mat = confusion_matrix(y_test, y_pred)
fig, ax = plt.subplots(figsize=(10,10))
sns.heatmap(conf_mat, annot=True, fmt='d', xticklabels=label_id_df.class_name.values, yticklabels=label_id_df.class_name.values)
plt.ylabel('Actual')
plt.xlabel('Predicted')
plt.show()

so easy!

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值