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)