概述
在機器學習中,感知機(perceptron)是二分類的線性分類模型,屬於監督學習算法。輸入為實例的特征向量,輸出為實例的類別(取+1和-1)。
感知機對應於輸入空間中將實例划分為兩類的分離超平面。感知機旨在求出該超平面,為求得超平面導入了基於誤分類的損失函數,利用梯度下降法 對損失函數進行最優化(最優化)。
感知機的學習算法具有簡單而易於實現的優點,分為原始形式和對偶形式。感知機預測是用學習得到的感知機模型對新的實例進行預測的,因此屬於判別模型。
感知機由Rosenblatt於1957年提出的,是神經網絡和支持向量機的基礎。
定義
假設輸入空間(特征向量)為,輸出空間為
。
輸入
表示實例的特征向量,對應於輸入空間的點;
輸出
表示示例的類別。
由輸入空間到輸出空間的函數為
稱為感知機。其中,參數w叫做權值向量(weight),b稱為偏置(bias)。表示w和x的點積
sign為符號函數,即
感知機算法就是要找到一個超平面將我們的數據分為兩部分。
超平面就是維度比我們當前維度空間小一個維度的空間, 例如:我們當前的維度是二維的空間(由數據維度確定,x有多少列就有多大的維度),那么超平面就是一維的,即一條直線。如下圖
算法步驟
數據集:
其中:
我們現在就是要找到一個超平面:
將數據集划分為正負兩部分:
如果能得到這樣一個超平面,則稱我們的數據集T是線性可分的, 否則稱數據集T是線性不可分的
損失函數
感知機的損失函數是誤分類點到超平面S的總距離
對於誤分類的點:
假設誤分類點的集合為M,所有誤分類點到超平面S的距離:
所以感知機的損失函數為:
我們的問題就是要找到最優的w, b, 使得損失函數最小。
梯度下降算法
我們采用梯度下降算法:
梯度下降法就是利用導數,然后沿着導數的方向下降, 最后得到最優的解, 如圖:
首先選擇w0, b0,一般初始化為0.
然后分別對w, b求導:
選擇合適的步長, 我們稱為學習率。
更新w,b:
這樣, 通過不斷的更新w, b, 減小了損失函數,我們得到了最優的解
感知機算法代碼
代碼在這里,翻我牌子
制作數據
%pylab
%matplotlib inline
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
iris = load_iris()#導入iris數據集
data = iris.data
data = data[:100]
labels = iris.target
labels = labels[:100]
feature_name = iris.feature_names
print("feature_name", feature_name)
#我們選擇了sepal length (cm)', 'sepal width (cm)',並且更改了labels
data = data[:, 0:2]
labels[labels == 0] = -1
feature_name = feature_name[:2]
X_train, X_test, y_train, y_test = train_test_split(data, labels)#划分數據集
定義類
class my_perceptron():
#初始化w,b,學習率
def __init__(self, lr=0.01):
self.w = 0
self.b = 0
self.lr = lr
def fit(self, X, y):
w = np.zeros(len(X[0]))
b = 0
lr = self.lr
all_true = False
#只要存在誤分類點就繼續循環
while not all_true:
all_true = True
for i in range(len(X)):
#誤分類條件
if y[i]*(np.dot(w, X[i]) + b) <= 0:
all_true = False
#更新w,b
w += lr*y[i]*X[i]
b += lr*y[i]
self.w = w
self.b = b
def predict(self, X):
res = []
for i in range(len(X)):
if np.dot(self.w, X[i]) + b <= 0:
res.append(-1)
else:
res.append(1)
return np.array(res)
def score(self, y_predict, y_test):
return np.mean(y_predict == y_test)
代碼測試
clf = my_perceptron()
clf.fit(X_train, y_train)
w = clf.w
b = clf.b
#繪圖查看
plt.scatter(train[:50, 0], train[:50, 1])
plt.scatter(train[50:-1, 0], train[50:-1, 1])
xx = np.linspace(train[:, 0].min(), train[:, 0].max(), 100)
yy = -(w[0]*xx + b)/w[1]
plt.plot(xx, yy)
plt.xlabel(feature_names[0])
plt.ylabel(feature_names[1])