阅读 109

softmax逻辑回归,ols回归模型公式

softmax回归轮廓softmax回归也被称为多种或多种Logistic回归,是Logistic回归对多分类问题的推广。

针对这样的数据分布,我想要一种将该组数据分为四类的方法。

很明显,我们可以用四条直线分开这个数据。

softmax回归和Logistic回归的区别在于,softmax回归面临的是两种以上的分类问题,一般来说,进行的分类问题有几种类型,所以需要画几条直线,每条直线的作用是“http://www.sinw.sining

所记述的正是将某一类与其他所有类区分开的思想。

如何设计多分类的线性判别函数? 剩下的一对一的argmax对一的剩下

将多分类问题转化为c个“一对剩余”的两分类问题。 在这种方式中,需要c个判别函数,c是指应该区别的类别的个数。 这里,第c个判别函数fc将类别c的数据样本与不属于c的所有其他数据样本分离。

一对一

将多分类问题转化为c(c-1 ) /两个“一对一”二分类问题。 这种方式需要c(c-1 )/2个判别函数,其中第I,j个判别函数将类别I和类别j的数据样本分开。

argmax

argmax是一种改进的“一对剩余”方式,同样需要c个判别函数。

这个c个判别函数的一般表达式是:

f(x3360wc ) )=wcT x bc,c1,c ) f_c ) x3360w_c )=w^T_cx b_c,c(lbrace1,\cdots,c\rbb

对于一个样本x,如果存在一个类别c,则对于所有其他类别c(tilde ) c ) ) c )的fc ) x; w c ) f_c(x ); w_c ) fc(x ); wc ) katex parse error : got function '\tilde ' withnoargumentsassubscriptatposition : f _\tilde { c } (x; 在w\tilde{c…,x属于类别c。

函数时

f c ( x ; w c ) f_c(x;w_c) fc(x;wc),我们可以理解为它表示样本点 x i x_i xi关于这C条直线(C个判别函数)的距离判别。


我们先看一下三种判别方式能得到的区分效果。


可以看到,无论是“一对其余”还是“一对一”方式,都会有盲区。而且“argmax”方式对前面两种方式做了改进,使得这些盲区内的数据也可以被区分。

我们可以将argmax方式的判别函数看成是欧式距离的计算,显然,即使是“盲区”内的数据点,这些数据点关于直线的欧式距离是一定存在的,所以它一定是可以被划分的,所以在一定程度上解决了这个问题。

one-hot编码

Logistic回归输出的是一个范围为[0,1]的概率值,是因为Logistic回归面对的二分类问题,一个范围在[0,1]内的概率值可以明确的区分输出的结果是0类还是1类。

然而在softmax回归中,多类问题使分类结果的表示变得困难起来。

所以会对输出结果y进行one-hot编码,进行编码后使得这个结果y_hot可以清晰的表示结果所属的类别。

那么什么是one-hot编码呢?

我们直观的拿一个例子:

假设四分类问题中分类为1,2,3,4四类,分类y=1经过one-hot编码后,得到的结果是[1,0,0,0]。

是的,它是一个数组,或者说是一个向量。

那么同样的,分类y=2经过one-hot编码后得到的结果是[0,1,0,0],以此类推。

当然,在实际进行参数训练后得到的结果不可能是这么精确的值,我们知道分类问题得到的都是一些概率值。

所以我们得到的值可能是y1 = [0.1,0.2,0.5,0.2],y2 = [0.7,0.1,0.1,0.1]…

不过结果依然很显然了,y1表示这个数据更趋向于3类,y2表示的数据更趋向于1类。

softmax用到的函数 softmax激活函数one-hot编码交叉熵损失函数梯度下降法

与Logistic回归不同的是激活函数,softmax回归用到的激活函数是softmax。


softmax和sigmoid函数的目的都是将 w 1 ∗ x 1 + w 2 ∗ x 2 + b w_1*x_1+w_2*x_2+b w1∗x1+w2∗x2+b得到的值进行一个归一化,将值压缩到区间(0,1)内,这样便于所有的值进行比较。

代码实现

引入所需库

import numpy as npimport matplotlib.pyplot as plt

随机生成数据集

np.random.seed(0)Num=100#0类别x1 = np.random.normal(-3,1,size=(Num))x2 = np.random.normal(-3,1,size=(Num))y= np.zeros(Num)data0 = np.array([x_1,x_2,y])#1类别x1 = np.random.normal(3,1,size=(Num))x2 = np.random.normal(-3,1,size=(Num))y= np.ones(Num)data1 = np.array([x_1,x_2,y])#2类别x1 = np.random.normal(-3,1,size=(Num))x2 = np.random.normal(3,1,size=(Num))y= np.ones(Num)*2data2 = np.array([x_1,x_2,y])#3类别x1 = np.random.normal(3,1,size=(Num))x2 = np.random.normal(3,1,size=(Num))y= np.ones(Num)*3data3 = np.array([x_1,x_2,y])data0 = data0.Tdata1 = data1.Tdata2 = data2.Tdata3 = data3.T

查看数据分布

plt.scatter(data0[:,0],data0[:,1],marker="o")plt.scatter(data1[:,0],data1[:,1],marker="+")plt.scatter(data2[:,0],data2[:,1],marker="v")plt.scatter(data3[:,0],data3[:,1],marker="s")


随机初始化权值与偏置

W = np.random.rand(4,2)b = np.random.rand(4,1)

打乱数据集

All_data=np.concatenate((data0,data1,data2,data3))np.random.shuffle(All_data)

查看初始化后判别函数的情况

x=np.arange(-5,5)y1=(-W[0,0]*x-b[0])/W[0,1]y2=(-W[1,0]*x-b[1])/W[1,1]y3=(-W[2,0]*x-b[2])/W[2,1]y4=(-W[3,0]*x-b[3])/W[3,1]plt.scatter(data0[:,0],data0[:,1],marker="o")plt.scatter(data1[:,0],data1[:,1],marker="+")plt.scatter(data2[:,0],data2[:,1],marker="v")plt.scatter(data0[:,0],data3[:,1],marker="s")plt.plot(x,y1)plt.plot(x,y2)plt.plot(x,y3)plt.plot(x,y4)


定义函数

#softmax(x)=e^x/sum(e^x)def softmax_matrix(z):#当z不是一维时 exp = np.exp(z) sum_exp = np.sum(np.exp(z),axis=1,keepdims=True) return exp/sum_expdef softmax_vector(z):#当z是一维时 return np.exp(z)/np.sum(np.exp(z))#对Y进行one-hot编码#temp = {0,1,2,3}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 return one_hot# 计算 y_hatdef compute_y_hat(W,X,b): return np.dot(X,W.T)+b.T#计算交叉熵def cross_entropy(y,y_hat): loss = -(1/len(y))*np.sum(y*np.log(y_hat)) return loss

进行训练

#w = w + lr*gradlr = 0.01loss_list=[]for i in range(1000): #计算loss y_hat = softmax_matrix(compute_y_hat(W,train_data_X,b)) y = one_hot(train_data_Y) loss = cross_entropy(y,y_hat) loss_list.append(loss) #计算梯度 grad_w = (1/len(train_data_X))*(np.dot(train_data_X.T,(y-y_hat)).T) grad_b = (1/len(train_data_X))*np.sum(y-y_hat) #更新参数 W = W + lr*grad_w b = b + lr*grad_b # 输出 if i%100==1 : print("i:%d , loss:%f"%(i,loss))


绘制训练后的分类情况

x=np.arange(-5,5)y1=(-W[0,0]*x-b[0])/W[0,1]y2=(-W[1,0]*x-b[1])/W[1,1]y3=(-W[2,0]*x-b[2])/W[2,1]y4=(-W[3,0]*x-b[3])/W[3,1]plt.scatter(data0[:,0],data0[:,1],marker="o")plt.scatter(data1[:,0],data1[:,1],marker="+")plt.scatter(data2[:,0],data2[:,1],marker="v")plt.scatter(data3[:,0],data3[:,1],marker="s")plt.plot(x,y1)plt.plot(x,y2)plt.plot(x,y3)plt.plot(x,y4)


查看loss值下降曲线

plt.plot(loss_list)


文章分类
代码人生
版权声明:本站是系统测试站点,无实际运营。本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 XXXXXXo@163.com 举报,一经查实,本站将立刻删除。
相关推荐