SVM 是有监督的学习模型,我们需要事先对数据打上分类标签,通过求解最大分类间隔来求解二分类问题。如果要求解多分类问题,可以将多个二分类器组合起来形成一个多分类器。
如何在 sklearn 中使用 SVM
# 导包 from sklearn import svm
SVM 既可以做回归,也可以做分类器。
当用 SVM 做回归的时候,我们可以使用 SVR 或 LinearSVR。SVR 的英文是 Support Vector Regression。
当做分类器的时候,我们使用的是 SVC 或者 LinearSVC。SVC 的英文是 Support Vector Classification。
从名字上你能看出 LinearSVC 是个线性分类器,用于处理线性可分的数据,只能使用线性核函数。SVM是通过核函数将样本从原始空间映射到一个更高维的特质空间中,这样就使得样本在新的空间中线性可分。
如果是针对非线性的数据,需要用到 SVC。在 SVC 中,我们既可以使用到线性核函数(进行线性划分),也能使用高维的核函数(进行非线性划分)。
如何创建一个 SVM 分类器呢?



如何用 SVM 进行乳腺癌检测
医疗人员采集了患者乳腺肿块经过细针穿刺 (FNA) 后的数字化图像,并且对这些数字图像进行了特征提取,这些特征可以描述图像中的细胞核呈现。肿瘤可以分成良性和恶性。部分数据截屏如下所示:

数据表一共包括了 32 个字段,代表的含义如下:

上面的表格中,mean 代表平均值,se 代表标准差,worst 代表最大值(3 个最大值的平均值)。每张图像都计算了相应的特征,得出了这 30 个特征值(不包括 ID 字段和分类标识结果字段 diagnosis),实际上是 10 个特征值(radius、texture、perimeter、area、smoothness、compactness、concavity、concave points、symmetry 和fractal_dimension_mean)的 3 个维度,平均、标准差和最大值。这些特征值都保留了 4 位数字。字段中没有缺失的值。在 569 个患者中,一共有 357 个是良性,212 个是恶性。
我们的目标是生成一个乳腺癌诊断的 SVM 分类器,并计算这个分类器的准确率。首先设定项目的执行流程:

-
首先我们需要加载数据源;
-
在准备阶段,需要对加载的数据源进行探索,查看样本特征和特征值,这个过程你也可以使用数据可视化,它可以方便我们对数据及数据之间的关系进一步加深了解。然后按照“完全合一”的准则来评估数据的质量,如果数据质量不高就需要做数据清洗。数据清洗之后,你可以做特征选择,方便后续的模型训练;
-
在分类阶段,选择核函数进行训练,如果不知道数据是否为线性,可以考虑使用 SVC(kernel=‘rbf’) ,也就是高斯核函数的 SVM 分类器。然后对训练好的模型用测试集进行评估。
加载数据并对数据做部分的探索:
# 加载数据集,你需要把数据放到目录中
data = pd.read_csv("./data.csv")
# 数据探索
# 因为数据集中列比较多,我们需要把 dataframe 中的列全部显示出来
# pd.set_option('display.max_columns', 10) # 最多显示10列,超过用省略号显示
print(data.columns)
print(data.head(5))
print(data.describe())
# 部分运行结果:
Index(['id', 'diagnosis', 'radius_mean', 'texture_mean', 'perimeter_mean',
'area_mean', 'smoothness_mean', 'compactness_mean', 'concavity_mean',
'concave points_mean', 'symmetry_mean', 'fractal_dimension_mean',
'radius_se', 'texture_se', 'perimeter_se', 'area_se', 'smoothness_se',
'compactness_se', 'concavity_se', 'concave points_se', 'symmetry_se',
'fractal_dimension_se', 'radius_worst', 'texture_worst',
'perimeter_worst', 'area_worst', 'smoothness_worst',
'compactness_worst', 'concavity_worst', 'concave points_worst',
'symmetry_worst', 'fractal_dimension_worst'],
dtype='object')
id diagnosis radius_mean texture_mean perimeter_mean area_mean \
0 842302 M 17.99 10.38 122.80 1001.0
1 842517 M 20.57 17.77 132.90 1326.0
2 84300903 M 19.69 21.25 130.00 1203.0
3 84348301 M 11.42 20.38 77.58 386.1
4 84358402 M 20.29 14.34 135.10 1297.0
数据清洗:
运行结果中,你能看到 32 个字段里,id 是没有实际含义的,可以去掉。diagnosis 字段的取值为 B 或者 M,我们可以用 0 和 1 来替代。另外其余的 30 个字段,其实可以分成三组字段,下划线后面的 mean、se 和 worst 代表了每组字段不同的度量方式,分别是平均值、标准差和最大值。
# 将特征字段分成 3 组
features_mean= list(data.columns[2:12])
features_se= list(data.columns[12:22])
features_worst=list(data.columns[22:32])
# 数据清洗
# ID 列没有用,删除该列
data.drop("id",axis=1,inplace=True)
# 将 B 良性替换为 0,M 恶性替换为 1
data['diagnosis']=data['diagnosis'].map({'M':1,'B':0})
然后我们要做特征字段的筛选,首先需要观察下 features_mean 各变量之间的关系,这里我们可以用 DataFrame 的 corr() 函数,然后用热力图帮我们可视化呈现。同样,我们也会看整体良性、恶性肿瘤的诊断情况。
# 将肿瘤诊断结果可视化 sns.countplot(data['diagnosis'],label="Count") plt.show() # 用热力图呈现 features_mean 字段之间的相关性 corr = data[features_mean].corr() plt.figure(figsize=(14,14)) # annot=True 显示每个方格的数据 sns.heatmap(corr, annot=True) plt.show()



# 特征选择 features_remain = ['radius_mean','texture_mean', 'smoothness_mean','compactness_mean','symmetry_mean', 'fractal_dimension_mean']
对特征进行选择之后,我们就可以准备训练集和测试集:
# 抽取 30% 的数据作为测试集,其余作为训练集 train, test = train_test_split(data, test_size = 0.3)# in this our main data is splitted into train and test # 抽取特征选择的数值作为训练和测试数据 train_X = train[features_remain] train_y=train['diagnosis'] test_X= test[features_remain] test_y =test['diagnosis']
在训练之前,我们需要对数据进行规范化,这样让数据同在同一个量级上,避免因为维度问题造成数据误差:
# 采用 Z-Score 规范化数据,保证每个特征维度的数据均值为 0,方差为 1 ss = StandardScaler() train_X = ss.fit_transform(train_X) test_X = ss.transform(test_X)
最后我们可以让 SVM 做训练和预测了:
# 创建 SVM 分类器
model = svm.SVC()
# 用训练集做训练
model.fit(train_X,train_y)
# 用测试集做预测
prediction=model.predict(test_X)
print('准确率: ', metrics.accuracy_score(prediction,test_y))
# 运行结果 准确率: 0.9181286549707602

from sklearn import svm
import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn import metrics
def train_func(func, features_remain, desc):
#分类阶段:模型训练
#抽取30%的数据作为测试集,其余作为训练集
train, test = train_test_split(data, test_size=0.3)
train_x = train[features_remain]
train_y = train['diagnosis']
test_x = test[features_remain]
test_y = test['diagnosis']
ss = StandardScaler()
train_x = ss.fit_transform(train_x)
test_x = ss.transform(test_x)
#创建SVM分类器
if(func == "linear"):
model = svm.LinearSVC()
else:
model = svm.SVC()
#用训练集做训练
model.fit(train_x, train_y)
#用测试集做预测
#分类阶段:模型评估
predict_y = model.predict(test_x)
infos1 = "测试集准确率:" + str(metrics.accuracy_score(predict_y, test_y))
predict_yy = model.predict(train_x)
infos2 = "训练集准确率:" + str(metrics.accuracy_score(predict_yy, train_y))
print(desc + ":" + infos1 + " " + infos2)
#准备阶段:数据探索
data = pd.read_csv('./breast_cancer_data-master/data.csv')
#把所有的列都显示出来(在打印的时候)
pd.set_option('display.max_columns', None)
features_mean = list(data.columns[2:12])
features_se = list(data.columns[12:22])
features_worst = list(data.columns[22:32])
#准备阶段:数据清洗,id列没有用,删除该列
data.drop("id", axis=1, inplace=True)
# 将B良性替换为0,M恶性替换为1
data['diagnosis']=data['diagnosis'].map({'M': 1, 'B': 0})
#准备阶段:数据可视化
sns.countplot(data['diagnosis'], label='Count')
plt.show()
corr = data[features_mean].corr()
plt.figure(figsize=(14,14))
sns.heatmap(corr, annot=True)
plt.show()
#分类阶段:特征选择
features_remain = ['radius_mean', 'texture_mean', 'smoothness_mean', 'compactness_mean', 'symmetry_mean', 'fractal_dimension_mean']
#分类阶段:模型训练+模型评估
train_func('svc', features_remain, 'svc_six')
train_func('svc', features_mean, 'svc_all')
train_func('linear', features_remain, 'linearsvc_six')
train_func('linear', features_mean, 'linearsvc_all')
