介绍
本次使用x1、x2两个参数进行0/1/2/3四类的多元分类问题模型的搭建
代码实现
import numpy as np
import matplotlib.pyplot as plt
np.random.seed(0)
num=100
x_1=np.random.normal(-3,1,size=(num))
x_2=np.random.normal(-3,1,size=(num))
y=np.zeros(num)
class0=np.array([x_1,x_2,y])
x_1=np.random.normal(3,1,size=(num))
x_2=np.random.normal(-3,1,size=(num))
y=np.ones(num)
class1=np.array([x_1,x_2,y])
x_1=np.random.normal(-3,1,size=(num))
x_2=np.random.normal(3,1,size=(num))
y=np.ones(num)*2
class2=np.array([x_1,x_2,y])
x_1=np.random.normal(3,1,size=(num))
x_2=np.random.normal(3,1,size=(num))
y=np.ones(num)*3
class3=np.array([x_1,x_2,y])
class0=class0.T
class1=class1.T
class2=class2.T
class3=class3.T
class0.shape
上述代码创建了以(0,0)为中心的四个方向区域的四类数据集。每类数据集的大小为(100,3)
可视化显示:
plt.scatter(class0[:,0],class0[:,1],marker='o')
plt.scatter(class1[:,0],class1[:,1],marker='*')
plt.scatter(class2[:,0],class2[:,1],marker='.')
plt.scatter(class3[:,0],class3[:,1],marker='s')
创建大数据集:
all_data=np.concatenate((class0,class1,class2,class3))
#all_data.shape (400,3)
打乱数据,并划分训练集与测试集
np.random.shuffle(all_data)
train_data_x=all_data[:300,:2]
train_data_y=all_data[:300,-1].reshape(300,1)
test_data_x=all_data[300:,:2]
test_data_y=all_data[300:,-1].reshape(100,1)
#train_data_x.shape,train_data_y.shape
使用线性分割
y=w1x1+w2x2+b
#0=w1x+w2y+b
#y=-(w1*x+b)/w2
w=np.random.rand(4,2)
bias=np.random.rand(1,4)
plt.scatter(class0[:,0],class0[:,1],marker='o')
plt.scatter(class1[:,0],class1[:,1],marker='*')
plt.scatter(class2[:,0],class2[:,1],marker='.')
plt.scatter(class3[:,0],class3[:,1],marker='s')
x=np.arange(-5,5)
y1=-(w[0,0]*x+bias[0,0])/w[0,1]
plt.plot(x,y1,'b')
x=np.arange(-5,5)
y2=-(w[1,0]*x+bias[0,1])/w[1,1]
plt.plot(x,y2,'g')
x=np.arange(-5,5)
y3=-(w[2,0]*x+bias[0,2])/w[2,1]
plt.plot(x,y3,'r')
x=np.arange(-5,5)
y4=-(w[3,0]*x+bias[0,3])/w[3,1]
plt.plot(x,y4,'y')
softmax函数
def softmax(z):
return np.exp(z)/np.sum(np.exp(z))
def softmax(z):
exp=np.exp(z)
sum_exp=np.sum(np.exp(z),axis=1,keepdims=True)
return exp/sum_exp
这里我们要对y做一个one_hot编码
one_hot 如temp1,2,3,4 ——[0,0,1,0]表示3
one_hot编码示意图如下:
def one_hot(temp):
one_hot=np.zeros((len(temp),len(np.unique(temp)))) #按照样本个数生成行数,按照非重复值生成列数
one_hot[np.arange(len(temp)),temp.astype(np.int).T]=1 #将对应位置设置为1
return one_hot
one_hot(train_data_y)
计算y_hat
def computer_y_hat(w,x,b):
return np.dot(x,w.T)+b
计算交叉熵
def cross_entropy(y,y_hat):
loss=-(1/len(y))*np.sum(y*np.log(y_hat))
return loss
更新参数
lr=0.001
all_loss=[]
for i in range(10000):
#计算loss
x=train_data_x
y=one_hot(train_data_y)
y_hat=softmax(computer_y_hat(w,x,bias))
loss=cross_entropy(y,y_hat)
all_loss.append(loss)
#计算梯度
grad_w=(1/len(x)*np.dot(x.T,(y_hat-y)))
grad_b=(1/len(x)*np.sum(y_hat-y))
#更新参数
w=w-lr*grad_w.T
bias=bias-lr*grad_b
#输出
if i%300 ==1:
print('i:%d,loss:%f'%(i,loss))
plt.plot(all_loss)
plt.scatter(class0[:,0],class0[:,1],marker='o')
plt.scatter(class1[:,0],class1[:,1],marker='*')
plt.scatter(class2[:,0],class2[:,1],marker='.')
plt.scatter(class3[:,0],class3[:,1],marker='s')
x=np.arange(-5,5)
y1=-(w[0,0]*x+bias[0,0])/w[0,1]
plt.plot(x,y1,'b')
x=np.arange(-5,5)
y2=-(w[1,0]*x+bias[0,1])/w[1,1]
plt.plot(x,y2,'g')
x=np.arange(-5,5)
y3=-(w[2,0]*x+bias[0,2])/w[2,1]
plt.plot(x,y3,'r')
x=np.arange(-5,5)
y4=-(w[3,0]*x+bias[0,3])/w[3,1]
plt.plot(x,y4,'y')
测试集预测
test_data_y.shape
def predict(x):
y_hat=softmax(computer_y_hat(w,x,bias))
return np.argmax(y_hat,axis=1)[:,np.newaxis]
acc=np.sum(predict(test_data_x)==test_data_y)/len(test_data_x)
print(acc)
1.0