基于SMO方法的SVM分类器实现,具体见上一篇博客:
这里主要是将自己写的SVM算法(my_SVM)与sklearnSVM算法进行比较。
代码的实现主要是基于:sklearn官方教程
遇到的主要问题:
- 分类模型拟合与预测的评估
- 生成器列表
- 模型训练与预测的疑惑
下面分别对遇到的问题展开说明
1 分类模型评估方法
关于二分类模型的评价指标,主要有 混淆矩阵、ROC、AUC等指标。
详细可以介绍可以见:
分类问题的评价指标
二分类问题评价指标
分类问题的评估指标一览
实际上,sklearn中提供的各种算法模型,其一般自带的都有score
方法可以用于对模型进行评估。这里为了控制变量,统一采用sklearn.metrics
提供的评估方法。
详细资料点这里
适用于二分类问题的方法:
调用 | 功能 |
---|---|
precision_recall_curve(y_true, probas_pred) | Compute precision-recall pairs for different probability thresholds |
roc_curve(y_true, y_score[, pos_label, …]) | Compute Receiver operating characteristic (ROC) |
2 生成器无法进行查看
sklearn中提供的例子有一行代码如下:
models_ori = (svm.SVC(kernel='linear', C = C),
svm.LinearSVC(C=C, max_iter=10000),
svm.SVC(kernel='rbf', gamma=0.7, C=C),
svm.SVC(kernel='poly', degree=3, gamma='auto', C=C))
# SVC与linearSVC的区别:https://www.cnblogs.com/zealousness/p/7757603.html
models_ori_fit = (clf.fit(X_train, y_train) for clf in models_ori)
# 创建的是生成器,这里将其改为列表。
# https://www.jianshu.com/p/6868cb724ba7
这里创建的models_ori_fit实际上为一个generator类型数据,在实际适用中会发现
无法直接调用moels_ori_fit[0].predict()
,而且在变量栏中也无法直接查看。
具体的解决方法通过采用list()的方法进行访问,具体见解决can’t pickle generator objects问题。这里,我直接通过将代码改为```models_ori_fit = [lf.fit(X_train, y_train) for clf in models_ori]``,这样返回值就是一个列表,从而可以进行访问。
3 模型训练与预测的问题
在sklearn中,以SVM举例。通过调用clf=svm.SVC()
即可以实例化一个SVM分类器,进一步可以调用其中的方法fit,即clf.fit(X,y)
进行训练,在训练完成后,实际上其返回值是self,即更新了clf。因此,在进行预测的时候同样可以调用clf.predict(X_test)
即可实现预测。其他的算法是一样的。
在训练完成后,可以调用属性fit_status_
查看训练是否正确,正确则返回值为0,否则为1(将报错)。
4 代码实现
"""
该脚本基于sklearn官方文档,实现对breast_cancer的二分类
其中,my_SVM是基于SMO自己实现的SVM分类器,ori_SVM是sklearn自带的SVM
这里仅选取 sepal length 和 sepal width 两个特征
分别采用 linear、RBF、poly三种核函数进行两种SVM算法的比较
"""
import mysvm as my
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
from sklearn import svm
import matplotlib.pyplot as plt
from sklearn.metrics import (precision_recall_curve, roc_curve, plot_roc_curve,
confusion_matrix, f1_score, accuracy_score, precision_score,
classification_report)
import pandas as pd
import numpy as np
def create_data():
"""
创建基于iris dataset的数据集
Returns
-------
X_train : TYPE
DESCRIPTION.
X_test : TYPE
DESCRIPTION.
y_train : TYPE
DESCRIPTION.
y_test : TYPE
DESCRIPTION.
"""
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]]) # 通过行号提取数据
# https://blog.csdn.net/w_weiying/article/details/81411257
for i in range(len(data)):
if data[i, -1] == 0:
data[i, -1] == -1
X_train, X_test, y_train, y_test = train_test_split(
data[:,:2], data[:, -1], test_size = 0.25, random_state=2020)# 数据打乱及划分
return X_train, X_test, y_train, y_test
# =============================================================================
# 模型训练与预测
# 模型再进行拟合后,就可以用来预测新的值
# 如:clf = svm.SVC(); clf.fit(X_train, y_train);clf.predict(X_test)
# 即当clf.fit执行完之后会返回一个新的训练完成的clf
# 可以调用clf.fit_status_查看是否正确训练,0则为correctly fitting
X_train, X_test, y_train, y_test = create_data()
C = 2.0 # 设置惩罚项系数,设置为1时,自己编写的SVM会报错
models_ori = (svm.SVC(kernel='linear', C = C),
svm.LinearSVC(C=C, max_iter=1000),
svm.SVC(kernel='rbf', gamma=0.7, C=C),
svm.SVC(kernel='poly', degree=3, gamma='auto', C=C))
# SVC与linearSVC的区别:https://www.cnblogs.com/zealousness/p/7757603.html
models_ori = [clf.fit(X_train, y_train) for clf in models_ori]
# 创建的是生成器,这里将其改为列表。
# https://www.jianshu.com/p/6868cb724ba7
y_pre_ori = [clf.predict(X_test) for clf in models_ori] #预测输出
models_my = [my.SVM(kernel='linear', max_iter=1000, C=C),
my.SVM(kernel='poly', max_iter=1000, C=C),
my.SVM(kernel='rbf', max_iter=1000, C=C)]
y_pre_my = []
for i in range(3):
models_my[i].fit(X_train, y_train) # 训练
# y_pre_my[i] = models_my[i].predicts(X_test) # 空数组不能直接指定位置
y_pre_my.append(models_my[i].predicts(X_test))
# =============================================================================
# 模型预测结果评估
y_pre = y_pre_ori + y_pre_my #前四组为sklearn,后三组为自己写的SVM
cm = [] # confusion_matrix
f1_scores = [] # https://blog.csdn.net/qq_14997473/article/details/82684300
ACC = [] #
for i in range(len(y_pre)):
cm.append(confusion_matrix(y_test, y_pre[i]))
# https://blog.csdn.net/shenxiaoming77/article/details/72627882
f1_scores.append(f1_score(y_test, y_pre[i]))
ACC.append(accuracy_score(y_test, y_pre[i]))
print('预测准确率:' , ACC)
print('预测f1_score' , f1_scores)
scores = pd.DataFrame([f1_scores, ACC],
columns = ['linear svc','linearSVC','rbf svc',
'poly svc','linear SVM', 'poly SVM', 'rbf SVM'],
index = ['f1_score','Accuracy score'])
#显示所有列
pd.set_option('display.max_columns', None)
print('模型结果比较', scores)
运行结果如下:
linear svc linearSVC rbf svc poly svc linear SVM poly SVM rbf SVM
f1_score 0.96 0.96 0.96 0.96 0.642857 0.64 0.00
Accuracy score 0.96 0.96 0.96 0.96 0.600000 0.64 0.52