感知器算法

感知器(perceptron)是二类分类的线性分类模型,它的思想很简单,就是在一个二维空间中寻找一条直线将红点和蓝点分开,类比到高维空间中,感知机模型尝试寻找一个超平面,将所有二元类别分开。

如果我们找不到这么一条直线的话怎么办?找不到的话那就意味着类别线性不可分(图3),也就意味着感知机模型不适合你的数据的分类。使用感知机一个最大的前提,就是数据是线性可分的。

伪码表示:

w=(0,0),b=0,done=False
while not done:
    done=True
        for i=1,2,...,m:
            if y(i)Sign(<w,x(i)>+b)≤ 0:
                w←w+y(i)x(i)
                b←b+y(i)
                done =False
return w,b

在perceptron.py中编写以下感知器代码:

import numpy as np
class Perceptron:
    def fit(self, X, y): #训练
        m, n = X.shape                    # X  m*n矩阵
        w = np.zeros((n, 1))              # w  n*1列向量
        b = 0
        done = False
        while not done:                  #done==True 结束
            done = True
            for i in range(m):
                x = X[i].reshape(1, -1)        # x  1*n行向量
                if y[i] * (x.dot(w) + b) <= 0: #样本(x[i],y[i])位于直线错误一侧
                    w = w + y[i] * x.T         # 更新 w  
                    b = b + y[i]               # 更新 b
                    done = False
        self.w = w    #得到模型的参数 w
        self.b = b    #模型参数 b

    def predict(self, X):     #预测x的标签
        return np.sign(X.dot(self.w) + self.b)  #预测标签 +1或-1

鸢尾花分离问题

思路

这里取到的是鸢尾花的所有数据,我们只需要前两项的数据就够了

from sklearn import datasets
iris = datasets.load_iris() 
X = iris["data"][:, (0, 1)]   # 取前两列, 特征维度n=2

划分训练集和测试集

'''
参数1:被划分的样本特征集,参数2:被划分的样本标签。
test_size:如果是浮点数,在0-1之间,表示样本占比;如果是整数的话就是样本的数量
random_state:是随机数的种子。
'''
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.4)

计算分离线

line = -w[0]/w[1] * x0 - b/w[1] #分离线 已知w,b,x0,求x1,  w0x0+w1x1+b=0 ,  x1即line

绘图

plt.figure()
plt.axis([4,8,1,5])
plt.title("Test Set")
'''
X[:, 0][y == 1]从X取出第0维度的所有数据集并筛选出标签为1的数据集
X[:, 1][y == 1]从X取出第1维度的所有数据集并筛选出标签为1的数据集
(X[:, 0][y == 1],X[:, 1][y == 1])就构成了一个二维坐标
'''
plt.plot(X_test[:, 0][y_test == 1], X_test[:, 1][y_test == 1], "bs", ms=3)    #正例蓝色点
plt.plot(X_test[:, 0][y_test == -1], X_test[:, 1][y_test == -1], "yo", ms=3)  #负例黄色点
x0 = np.linspace(4, 8, 200)
line = -w[0]/w[1] * x0- b/w[1]   #分离线 w0x0+w1x1+b=0 ,  line即x1
plt.plot(x0, line)
plt.show()

整合起来就是

import matplotlib.pyplot as plt
import numpy as np
from sklearn import datasets
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score
from perceptron import Perceptron#感知器类


#导入鸢尾花数据集,导入的数据是一种字典形式,特征存储在iris.data中,标签存储在iris.target中
iris = datasets.load_iris()   #导入数据Iris dataset
X = iris["data"][:, (0, 1)]   # 前两列, 特征维度n=2
y = 2 * (iris["target"] == 0).astype(np.int) - 1 #标签  -1或+1

'''
训练集、测试集划分
参数1:被划分的样本特征集,参数2:被划分的样本标签。
test_size:如果是浮点数,在0-1之间,表示样本占比;如果是整数的话就是样本的数量
random_state:是随机数的种子。
'''
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.4)

#draw original data
plt.figure()
plt.axis([4, 8, 1, 5])        #axis([x_left, x_right, y_bottom, y_top]) 视窗大小
plt.title("Source Set")
plt.plot(X[:, 0][y == 1], X[:, 1][y == 1], "bs", ms=3)
plt.plot(X[:, 0][y == -1], X[:, 1][y == -1], "yo", ms=3)
plt.show()

#train a Perceptron model
model = Perceptron()         #声明Perceptron实例
model.fit(X_train, y_train)  #训练
w = model.w                  #model 的参数 w
b = model.b                  #model 的参数 b
print('w=', w)
print('b=', b)
#draw 对训练数据集进行分类,两类分离线
plt.figure()
plt.axis([4, 8, 1, 5])
plt.title("Training Set")
plt.plot(X_train[:, 0][y_train == 1], X_train[:, 1][y_train == 1] + 0.1, "bs", ms=3)
plt.plot(X_train[:, 0][y_train == -1], X_train[:, 1][y_train == -1] - 0.1, "yo", ms=3)
x0 = np.linspace(4, 8, 200)     #在[4,8]均匀取200个点
line = -w[0]/w[1] * x0 - b/w[1] #分离线 已知w,b,x0,求x1,  w0x0+w1x1+b=0 ,  x1即line
plt.plot(x0, line)
plt.show()

#draw 对测试数据集进行分类,两类分离线
plt.figure()
plt.axis([4,8,1,5])
plt.title("Test Set")
plt.plot(X_test[:, 0][y_test == 1], X_test[:, 1][y_test == 1], "bs", ms=3)    #正例蓝色点
plt.plot(X_test[:, 0][y_test == -1], X_test[:, 1][y_test == -1], "yo", ms=3)  #负例黄色点
x0 = np.linspace(4, 8, 200)
line = -w[0]/w[1] * x0- b/w[1]   #分离线 w0x0+w1x1+b=0 ,  line即x1
plt.plot(x0, line)
plt.show()
#本例 :感知器算法在训练样本上训练,得到w,b参数,画出两类样本的分离线
y_pred = model.predict(X_test)       #测试
accuracy = accuracy_score(y_test, y_pred) #测试结果的评价 sklearn.metrics.accuracy_score
print("accuracy= {}".format(accuracy))     #输出正确率

墨渍分类问题

与鸢尾花问题的异同

此问题与鸢尾花分类问题思路近乎相同,只有几个不同点。

墨渍数据获取

from sklearn.datasets.samples_generator import make_blobs
''''
make_blobs()函数是为聚类产生数据集 产生一个数据集和相应的标签
n_samples:表示数据样本点个数,默认值100
centers:产生数据的中心点,默认值3
n_features:表示数据的维度,默认值是2
cluster_std:数据集的标准差,浮点数或者浮点数序列,默认值1.0
random_state:官网解释是随机生成器的种子
center_box:中心确定之后的数据边界,默认值(-10.0, 10.0)
shuffle :洗乱,默认值是True
'''
X, y = make_blobs(n_samples= 100, centers=2, n_features=2, cluster_std=0.6)
#X为数据集,y为X对应的标签

绘图

这里与鸢尾花问题唯一的不同点就是鸢尾花的特征值有固定的范围,而此处生成的随机墨渍数据没有固定范围。因此,绘图时图的大小要根据数据的范围而定。

可以考虑求出数据集的最大值和最小值,就确定了点的范围。

# axis([x_left, x_right, y_bottom, y_top]) 视窗大小
plt.axis([min(X_train[:, 0]),max(X_train[:, 0]),min(X_train[:, 1]),max(X_train[:, 1])])

画分割线:

x0 = np.linspace(min(X_train[:, 0]),max(X_train[:, 0]), 200)     #在[4,8]均匀取200个点
line = -w[0]/w[1] * x0 - b/w[1] #分离线 已知w,b,x0,求x1,  w0x0+w1x1+b=0 ,  x1即line
plt.plot(x0, line)

其余步骤同鸢尾花问题,在此略过。

整合起来就是

import matplotlib.pyplot as plt
import numpy as np
from sklearn import datasets
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score
from perceptron import Perceptron#感知器类


#生成墨水数据
X , y = datasets.make_blobs(n_samples= 200, centers=2, n_features=2, cluster_std=1.2)
y = 2 * (y == 0).astype(np.int) - 1 #标签  -1或+1

'''
训练集、测试集划分
参数1:被划分的样本特征集,参数2:被划分的样本标签。
test_size:如果是浮点数,在0-1之间,表示样本占比;如果是整数的话就是样本的数量
random_state:是随机数的种子。
'''
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.4)

#draw original data
plt.figure()
# axis([x_left, x_right, y_bottom, y_top]) 视窗大小
plt.axis([min(X[:, 0]),max(X[:, 0]),min(X[:, 1]),max(X[:, 1])])
plt.title("Source Set")
plt.plot(X[:, 0][y == 1], X[:, 1][y == 1], "bs", ms=3)
plt.plot(X[:, 0][y == -1], X[:, 1][y == -1], "yo", ms=3)
plt.show()

#train a Perceptron model
model = Perceptron()         #声明Perceptron实例
model.fit(X_train, y_train)  #训练
w = model.w                  #model 的参数 w
b = model.b                  #model 的参数 b
print('w=', w)
print('b=', b)
#draw 对训练数据集进行分类,两类分离线
plt.figure()
# axis([x_left, x_right, y_bottom, y_top]) 视窗大小
plt.axis([min(X_train[:, 0]),max(X_train[:, 0]),min(X_train[:, 1]),max(X_train[:, 1])])
plt.title("Training Set")
plt.plot(X_train[:, 0][y_train == 1], X_train[:, 1][y_train == 1] + 0.1, "bs", ms=3)
plt.plot(X_train[:, 0][y_train == -1], X_train[:, 1][y_train == -1] - 0.1, "yo", ms=3)
x0 = np.linspace(min(X_train[:, 0]),max(X_train[:, 0]), 200)     #在[4,8]均匀取200个点
line = -w[0]/w[1] * x0 - b/w[1] #分离线 已知w,b,x0,求x1,  w0x0+w1x1+b=0 ,  x1即line
plt.plot(x0, line)
plt.show()

#draw 对测试数据集进行分类,两类分离线
plt.figure()
plt.axis([min(X_test[:, 0]),max(X_test[:, 0]),min(X_test[:, 1]),max(X_test[:, 1])])
plt.title("Test Set")
plt.plot(X_test[:, 0][y_test == 1], X_test[:, 1][y_test == 1], "bs", ms=3)    #正例蓝色点
plt.plot(X_test[:, 0][y_test == -1], X_test[:, 1][y_test == -1], "yo", ms=3)  #负例黄色点
x0 = np.linspace(min(X_test[:, 0]),max(X_test[:, 0]), 200)
line = -w[0]/w[1] * x0- b/w[1]   #分离线 w0x0+w1x1+b=0 ,  line即x1
plt.plot(x0, line)
plt.show()
#本例 :感知器算法在训练样本上训练,得到w,b参数,画出两类样本的分离线
y_pred = model.predict(X_test)       #测试
accuracy = accuracy_score(y_test, y_pred) #测试结果的评价 sklearn.metrics.accuracy_score
print("accuracy= {}".format(accuracy))     #输出正确率

分类效果

机器学习分类问题 机器学习分类问题


我一直在开辟我的天空