【火炉炼AI】机器学习014-用SVM构建非线性分类模型

【火炉炼AI】机器学习014-用SVM构建非线性分类模型

(本文所使用的Python库和版本号: Python 3.5, Numpy 1.14, scikit-learn 0.19, matplotlib 2.2 )

支持向量机(Support Vector Machine,SVM)是一种常见的判别方法,其基本模型是在特征空间上找到最佳的分离超平面,使得数据集上的正负样本间隔最大。SVM用来解决二分类问题的有监督学习算法,其可以解决线性问题,也可以通过引入核函数的方法来解决非线性问题。

本项目旨在使用SVM构建非线性分类模型来判别数据集的不同类别。


1. 准备数据集

首先来加载和查看数据集的一些特性。如下代码加载数据集并查看其基本信息

# 准备数据集
data_path='E:\PyProjects\DataSet\FireAI/data_multivar_2_class.txt'
df=pd.read_csv(data_path,header=None)
# print(df.head()) # 没有问题
print(df.info()) # 查看数据信息,确保没有错误
dataset_X,dataset_y=df.iloc[:,:-1],df.iloc[:,-1]
# print(dataset_X.head())
# print(dataset_X.info())
# print(dataset_y.head()) # 检查没问题
dataset_X=dataset_X.values
dataset_y=dataset_y.values

-------------------------------------输---------出--------------------------------

<class 'pandas.core.frame.DataFrame'>
RangeIndex: 300 entries, 0 to 299
Data columns (total 3 columns):
0 300 non-null float64
1 300 non-null float64
2 300 non-null int64
dtypes: float64(2), int64(1)
memory usage: 7.1 KB
None

--------------------------------------------完-------------------------------------

从上面的df.info()函数的结果可以看出,这个数据集有两个特征属性(0,1列,连续的float类型),一个标记(2列,离散的int型,只有两个类别),每一列都没有缺失值。然后来看看这个数据集中数据点的分布情况,如下图所示:

# 数据集可视化
def visual_2D_dataset(dataset_X,dataset_y):
    '''将二维数据集dataset_X和对应的类别dataset_y显示在散点图中'''
    assert dataset_X.shape[1]==2,'only support dataset with 2 features'
    plt.figure()
    classes=list(set(dataset_y)) 
    markers=['.',',','o','v','^','<','>','1','2','3','4','8'
             ,'s','p','*','h','H','+','x','D','d','|']
    colors=['b','c','g','k','m','w','r','y']
    for class_id in classes:
        one_class=np.array([feature for (feature,label) in 
                   zip(dataset_X,dataset_y) if label==class_id])
        plt.scatter(one_class[:,0],one_class[:,1],marker=np.random.choice(markers,1)[0],
                    c=np.random.choice(colors,1)[0],label='class_'+str(class_id))
    plt.legend()
    
visual_2D_dataset(dataset_X,dataset_y)
数据集中数据点的分布情况

我以前的很多文章都讲到了数据集的处理,拆分,准备等,此处的数据集比较简单,故而简单讲述一下。


2. 用SVM构建线性分类器

你没有看错,我就是想用SVM构建一个线性分类器来判别这个数据集。当然,即使是入门级的机器学习攻城狮们,也能看出,这个数据集是一个线性不可分类型,需要用非线性分类器来解决。所以,此处,我就用线性分类器来拟合一下,看看会有什么样的“不好”的结果。

# 从数据集的分布就可以看出,这个数据集不可能用直线分开
# 为了验证我们的判断,下面还是使用SVM来构建线性分类器将其分类

# 将整个数据集划分为train set和test set
from sklearn.model_selection import train_test_split
train_X, test_X, train_y, test_y=train_test_split(
    dataset_X,dataset_y,test_size=0.25,random_state=42)

# print(train_X.shape)  # (225, 2)
# print(train_y.shape)  # (225,)
# print(test_X.shape)  # (75, 2)

# 使用线性核函数初始化一个SVM对象。
from sklearn.svm import SVC
classifier=SVC(kernel='linear') # 构建线性分类器
classifier.fit(train_X,train_y)

-------------------------------------输---------出--------------------------------

SVC(C=1.0, cache_size=200, class_weight=None, coef0=0.0,
decision_function_shape='ovr', degree=3, gamma='auto', kernel='linear',
max_iter=-1, probability=False, random_state=None, shrinking=True,
tol=0.001, verbose=False)

--------------------------------------------完-------------------------------------

然后查看一下这个训练好的SVM线性分类器在训练集和测试集上的表现,如下为在训练集上的性能报告:

# 模型在训练集上的性能报告:
from sklearn.metrics import classification_report
plot_classifier(classifier,train_X,train_y)  # 分类器在训练集上的分类效果
target_names = ['Class-0', 'Class-1']
y_pred=classifier.predict(train_X)
print(classification_report(train_y, y_pred, target_names=target_names))
SVM线性分类器在训练集上的分类效果

-------------------------------------输---------出--------------------------------

precision recall f1-score support

Class-0 0.60 0.96 0.74 114
Class-1 0.89 0.35 0.50 111

avg / total 0.74 0.66 0.62 225

--------------------------------------------完-------------------------------------

很明显,从分类效果图和性能报告中,都可以看出这个模型很差,差到姥姥家了。。。
所以,更不用说,在测试集上的表现了,当然是一个差字了得。。。

# 分类器在测试集上的分类效果
plot_classifier(classifier,test_X,test_y)  

target_names = ['Class-0', 'Class-1']
y_pred=classifier.predict(test_X)
print(classification_report(test_y, y_pred, target_names=target_names))
SVM线性分类器在测试集上的分类效果

-------------------------------------输---------出--------------------------------

precision recall f1-score support

Class-0 0.57 1.00 0.73 36
Class-1 1.00 0.31 0.47 39

avg / total 0.79 0.64 0.59 75

--------------------------------------------完-------------------------------------


3. 用SVM构建非线性分类器

很明显,用线性分类器解决不了这个数据集的判别问题,所以我们就上马非线性分类器吧。

使用SVM构建非线性分类器主要是考虑使用不同的核函数,此处指讲述两种核函数:多项式核函数和径向基函数。

# 从上面的性能报告中可以看出,分类效果并不好
# 故而我们使用SVM建立非线性分类器,看看其分类效果
# 使用SVM建立非线性分类器主要是使用不同的核函数
# 第一种:使用多项式核函数:
classifier_poly=SVC(kernel='poly',degree=3) # 三次多项式方程
classifier_poly.fit(train_X,train_y)

# 在训练集上的表现为:
plot_classifier(classifier_poly,train_X,train_y)  

target_names = ['Class-0', 'Class-1']
y_pred=classifier_poly.predict(train_X)
print(classification_report(train_y, y_pred, target_names=target_names))
SVM多项式核函数的非线性分类器的分类效果

-------------------------------------输---------出--------------------------------

precision recall f1-score support

Class-0 0.92 0.85 0.89 114
Class-1 0.86 0.93 0.89 111

avg / total 0.89 0.89 0.89 225

--------------------------------------------完-------------------------------------

# 第二种:使用径向基函数建立非线性分类器
classifier_rbf=SVC(kernel='rbf') 
classifier_rbf.fit(train_X,train_y)

# 在训练集上的表现为:
plot_classifier(classifier_rbf,train_X,train_y)  

target_names = ['Class-0', 'Class-1']
y_pred=classifier_rbf.predict(train_X)
print(classification_report(train_y, y_pred, target_names=target_names))
SVM径向基函数的非线性分类器的分类效果

-------------------------------------输---------出--------------------------------

precision recall f1-score support

Class-0 0.96 0.96 0.96 114
Class-1 0.96 0.95 0.96 111

avg / total 0.96 0.96 0.96 225

--------------------------------------------完-------------------------------------

########################小**********结###############################

1. 用SVM构建非线性分类器很简单,只要使用不同的核函数就可以。

2. 对于这个数据集而言,使用了非线性分类器之后,分类效果得到了极大的改善,这个可以从性能报告中看出,而且,很明显两种非线性核函数,径向基函数rbf的分类效果要比多项式核函数的效果更好一些。

3. 这个模型也许还可以继续优化一些超参数,从而得到更好的分类效果。

#################################################################


注:本部分代码已经全部上传到(我的github)上,欢迎下载。

参考资料:

1, Python机器学习经典实例,Prateek Joshi著,陶俊杰,陈小莉译

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 219,701评论 6 508
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,649评论 3 396
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 166,037评论 0 356
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,994评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 68,018评论 6 395
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,796评论 1 308
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,481评论 3 420
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,370评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,868评论 1 319
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,014评论 3 338
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,153评论 1 352
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,832评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,494评论 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,039评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,156评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,437评论 3 373
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,131评论 2 356

推荐阅读更多精彩内容