【火炉炼AI】机器学习008-简单线性分类器解决二分类问题

【火炉炼AI】机器学习008-简单线性分类器解决二分类问题

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

分类问题,就是将数据点按照不同的类别区分开来,所谓人以类聚,物以群分,就是这个道理。以前的【机器学习001-007】都是讲解的回归问题,两者的不同之处在于:回归输出的结果是实数,并且一般是连续的实数值,而分类问题的输出结果是离散的某一个类别或不同类别的概率。

最简单的分类问题是二元分类,将整个样本划分为两个类别,比如将整个人类分为男人和女人(泰国人妖不在考虑范围内,呵呵)。稍微复杂一点的分类问题是多元分类,它将整个样本划分为多个(一般大于两个)不同类别,比如将家禽数据集可以划分为:鸡,鸭,鹅等,将家畜样本划分为:狗,猪,牛,羊等等。

下面从一个最简单的二元分类问题入手,看看二元分类器是如何构建的。


1. 准备数据集

由于二元分类问题比较简单,此处我们自己构建了一些数据点,并将这些数据点按照不同类别放入不同变量中,比如把所有第0类别的数据点都放置到class_0中,把所有第1类别的数据点放入class_1中,如下所示。

# 首先准备数据集
# 特征向量
X = np.array([[3,1], [2,5], [1,8], [6,4], [5,2], [3,5], [4,7], [4,-1]]) # 自定义的数据集
# 标记
y = [0, 1, 1, 0, 0, 1, 1, 0]

# 由于标记中只含有两类,故而将特征向量按照标记分割成两部分
class_0=np.array([feature for (feature,label) in zip(X,y) if label==0])
print(class_0) # 确保没有问题
class_1=np.array([feature for (feature,label) in zip(X,y) if label==1])
print(class_1)

# 划分也可以采用如下方法:两个打印后结果一样
# class_0=np.array([X[i] for i in range(len(X)) if y[i]==0])
# print(class_0)
# class_1=np.array([X[i] for i in range(len(X)) if y[i]==1])
# print(class_1)

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

[[ 3 1]
[ 6 4]
[ 5 2]
[ 4 -1]]
[[2 5]
[1 8]
[3 5]
[4 7]]

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

上面虽然构建了数据点,但是难以直观的看清这个二分类问题的数据点有什么特点,所以为了有更加直观的认识,一般会把数据点的散点图画出来,如下所示:

# 在图中画出这两个不同类别的数据集,方便观察不同类别数据的特点
plt.figure()
plt.scatter(class_0[:,0],class_0[:,1],marker='s',label='class_0')
plt.scatter(class_1[:,0],class_1[:,1],marker='x',label='class_1')
plt.legend()
两个类别数据集的分布图

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

1,本次研究的二分类问题是极其简单的分类问题,故而构建了8个样本的两个类别的数据点,每个类别有四个点。

2,为了更加直观的查看数据点的分布特点,一般我们要把数据点画在平面上,对数据点的分布情况有一个初步的了解,便于后面我们采用哪种分类器。

3,本次构建的数据集是由8行2列构成的特征矩阵,即8个样本,每个样本有两个features.

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


2. 构建简单线性分类器

所谓线性可分问题,是指在平面上可以通过一条直线(或更高维度上的,一个平面)来将所有数据点划分开来的问题,“可以用直线分开”是线性可分问题的本质。相对应的,“不可以用直线分开”便是线性不可分问题的本质,对于线性不可分问题,需要用曲线或曲面来将这些数据分开,对应的就是非线性问题。比如,上面自己定义的数据集可以用简单的直线划分开来,比如可以采用y=x这条直线分开,如下所示:

# 从上面图中可以看出,可以画一条直线轻松的将class_0和class_1两个数据点分开
# 其实有很多直线可以起到分类器的效果,此处我们只用最简单的y=x作为演示
plt.figure()
plt.scatter(class_0[:,0],class_0[:,1],marker='s',label='class_0')
plt.scatter(class_1[:,0],class_1[:,1],marker='x',label='class_1')
plt.plot(range(10),range(10),label='line_classifier') # 此处x=range(10), y=x
plt.legend()
使用一条直线可以将这两个数据集分开

实际上,可以采用非常多的直线来将本数据集的两个类别区分开来,如下图所示,这些直线是在斜率和截距上稍微调整而来。

可以分开的直线有很多条

那么,这么多直线都可以解决简单分类问题,肯定会有一条最佳直线,能够达到最佳的分类效果。下面,使用sklearn模块中的SGD分类器构建最佳直线分类器。如下代码:

# 上面虽然随机的选择了一条直线(y=x)作为分类器,但很多时候我们不知道分类
# 下面构建一个SGD分类器,它使用随机梯度下降法来训练
# 训练之前需要对数据进行标准化,保证每个维度的特征数据方差为1,均值为0,避免某个特征值过大而成为影响分类的主因
from sklearn.preprocessing import StandardScaler
ss=StandardScaler()
X_train=ss.fit_transform(X) # 由于本项目数据集太少,故而全部用来train

# 构建SGD分类器进行训练
from sklearn.linear_model import SGDClassifier
sgdClassifier=SGDClassifier(random_state=42)
sgdClassifier.fit(X_train,y) # y作为label已经是0,1形式,不需进一步处理

# 使用训练好的SGD分类器对陌生数据进行分类
X_test=np.array([[3,2],[2,3],[2.5,2.4],[2.4,2.5],[5,8],[6.2,5.9]])
X_test=ss.fit_transform(X_test) # test set也要记过同样的处理
test_predicted=sgdClassifier.predict(X_test)
print(test_predicted)

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

[0 1 1 1 1 0]

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

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

1,使用sklearn中的SGDClassifier可以对数据集进行简单的线性分类,达到比较好的分类效果。

2,在数据集的特征上,貌似x>y时,数据属于class_0, 而x<y时,数据属于class_1,SGDClassifier模型在测试数据集上也基本能够正确划分,只有在x和y大体相等的关键点处容易出现错误判断。

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


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

参考资料:

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

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

推荐阅读更多精彩内容