import numpy as np
import matplotlib.pyplot as plt
classMultiPerceptron:def__init__(self):# the shape of w :(n)
self._w =Nonedeffit(self, x, y, lr=1e-3, epoch=1000):
x = np.asarray(x, np.float32)
y = np.asarray(y, np.float32)# (x_features_num,1)
self._w = np.zeros([x.shape[1],y.shape[1]])for _ inrange(epoch):# 注意这里的实现是x点成w
y_pred = x.dot(self._w)# acturly it is dL/dw
dw =2*x.T.dot(y_pred - y)
self._w -= lr*dw
defpredict(self,x):
y_pred = np.asarray(x, np.float32).dot(self._w)return np.argmax(y_pred, axis=1).astype(np.float32)
验证
# x =(200,2) ,y = (200,5) y is one-hot vector
x, y = gen_five_clusters()# now y is a class label
label = np.argmax(y, axis=1)
perceptron = MultiPerceptron()
perceptron.fit(x,y)
visualize2d(perceptron,x,label,draw_background=True)print("Acc: {:8.6} %".format((perceptron.predict(x)== label).mean()*100))
辅助函数
import numpy as np
import matplotlib.pyplot as plt
from math import pi
defgen_five_clusters(size=200):
x = np.random.randn(size)*2
y = np.random.randn(size)*2
z = np.full(size,-1)
mask1, mask2 = x + y >=1, x + y >=-1
mask3, mask4 = x - y >=1, x - y >=-1
z[mask1 &~mask4]=0
z[mask1 & mask3]=1
z[~mask2 & mask3]=2
z[~mask2 &~mask4]=3
z[z ==-1]=4
one_hot = np.zeros([size,5])
one_hot[range(size), z]=1return np.c_[x, y].astype(np.float32), one_hot
defvisualize2d(clf, x, y, padding=0.2, draw_background=False):
axis, labels = np.array(x).T, np.array(y)
nx, ny, padding =400,400, padding
x_min, x_max = np.min(axis[0]), np.max(axis[0])
y_min, y_max = np.min(axis[1]), np.max(axis[1])
x_padding =max(abs(x_min),abs(x_max))* padding
y_padding =max(abs(y_min),abs(y_max))* padding
x_min -= x_padding
x_max += x_padding
y_min -= y_padding
y_max += y_padding
defget_base(nx, ny):
xf = np.linspace(x_min, x_max, nx)
yf = np.linspace(y_min, y_max, ny)
n_xf, n_yf = np.meshgrid(xf, yf)return xf, yf, np.c_[n_xf.ravel(), n_yf.ravel()]
xf, yf, base_matrix = get_base(nx, ny)
z = clf.predict(base_matrix).reshape([nx, ny])
n_label =len(np.unique(labels))
xy_xf, xy_yf = np.meshgrid(xf, yf, sparse=True)
colors = plt.cm.rainbow([i / n_label for i inrange(n_label)])[labels.astype(np.int)]
plt.figure()if draw_background:
plt.pcolormesh(xy_xf, xy_yf, z, cmap=plt.cm.Paired)else:
plt.contour(xf, yf, z, c='k-', levels=[0])
plt.scatter(axis[0], axis[1], c=colors)
plt.xlim(x_min, x_max)
plt.ylim(y_min, y_max)
plt.show()