softmax回归多元分类

介绍

本次使用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

猜你喜欢

转载自blog.csdn.net/weixin_48994268/article/details/109624477
今日推荐