在线时间98 小时
UID3573447
注册时间2019-7-2
NXP金币209371
TA的每日心情 | 开心 2020-12-18 12:56 |
---|
签到天数: 55 天 [LV.5]常住居民I
管理员
- 积分
- 1632
- 最后登录
- 2024-4-26
|
老树发新芽SVM的增量式训练
大家是不是以为我们的SVM篇就这样结束了?nonono,对于这样一位资深的老前辈来说,寥寥几篇怎能叙说尽,换句话来说,历经几十年的历练,还能屹立于ML之巅,必定拥有卓越的技术实力和深厚的专业底蕴。
不过,大家在用SVM时一定也注意到过SVM本身只支持单次训练,要怎么解释呢?意思就是说我们在训练一个SVM模型前,要事先指定好想要识别的类别或是任务,这样训练好之后,模型就只能针对所指定的任务了。如果想要再添加新的需求,那不好意思了,需要再重新制定任务,并且这个任务必须包含老任务,不然SVM就会喜新厌旧了,只能完成新任务。
这样一来是不是有点麻烦?有伙伴要问了,我们CNN就能支持增量学习,你这SVM看起来还是不太行啊。那么为了给我们的SVM大佬正名,今天小编就给大家带来一篇番外,利用一些小技巧实现SVM的增量式训练。直接上代码!!
继续使用我们的鸢尾花数据集,不过这次我们做点特殊的。我们将其作为一个单分类的数据集来使用,具体怎么做呢?让我们一步步来看:
鸢尾花数据集一共有150组样本,我们先选取前50组出来,训练一个单分类模型,目的是让其只能够识别一种样本,代码片段:
from sklearn import datasets
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.svm import OneClassSVM
from sklearn.metrics import accuracy_score
import numpy as np
# 加载数据集
iris = datasets.load_iris()
X = iris.data
y = iris.target
data_each = 50
X0 = X[:data_each]
y0 = y[:data_each]
# 构建支持向量机分类器
svm = OneClassSVM(kernel='rbf', nu=0.1)
# 在训练集上训练模型,选取前30组作为训练样本
svm.fit(X_train[:30])
# 在测试集上进行预测,选取后20组数据作为测试集
y_pred = svm.predict(X_train[30:])
print("ACC: ", (y_pred == 1).sum() / len(y_pred))
测试结果打印:
测试结果打印:
好的,接下来就是至关重要的一步了,我们知道SVM全称是支持向量机,那么其原理就是在训练样本重抽取一部分当作支持向量,即挑选出能够代表全体数据的灵魂数据。换句话说,这些支持向量本身就能代表当前类别的所有数据,通过和支持向量间的对比即可认定新数据是否属于同一类别。那么好,我们要做的就是将这些支持向量提取出来,并将其与新数据拼接在一起作为新的训练数据:
support_vector = svm.support_vectors_
# 拼接数据,将前一类别的支持向量与新数据结合
new_train_x = np.vstack([support_vector, X[data_each:2*data_each][:30]])
这里提前看一下支持向量,针对于第一个类别,支持向量有4个:
支持向量有4个
继续训练,并测试:
# 构建支持向量机分类器
svm = OneClassSVM(kernel='rbf', nu=0.1)
svm.fit(new_train_x)
# 在测试集上进行预测,拼接之前的数据集
y_pred = svm.predict(np.vstack([X0[30:], X[data_each:2*data_each][30:]]))
print("ACC: ", (y_pred == 1).sum() / len(y_pred))
测试结果:
测试结果:
再来看下新的支持向量:
新的支持向量
可以看到,在第一次支持向量的基础上,又增加了针对第二个类别的。同时根据测试精度,可以看出,通过添加第一次训练多得到的支持向量,而非将全体数据进行二次训练,能够达到同样的效果。也验证了我们的猜测:支持向量本身其实就是数据集的代表,只将其作为训练样本,完全能够替代全部数据。并以此为基础实现SVM模型的增量式训练。
|
|