Softmax和交叉熵的原理和实现

    对于分类问题,通常使用离散的数值来表示类别。模型输出可以是一个像图像类别这样的离散值。对于这样的离散值预测问题,我们可以使用诸如softmax回归在内的分类模型。和线性回归不同,softmax回归的输出单元从一个变成了多个,且引入了softmax运算使输出更适合离散值的预测和训练。

    虽然我们仍然可以使用回归模型来进行建模,并将预测值就近定点化到分类标签值这几个离散值之一,但这种连续值到离散值的转化通常会影响到分类质量。因此我们一般使用更加适合离散值输出的模型来解决分类问题。


softmax回归

1.png


softmax计算

2.png

    softmax其实是由logistic回归的推广,有兴趣可以看李航老师的《统计学习方法》。


标签概率分布

3.png


交叉熵损失函数

    上一篇博文《线性回归的原理和实现》里面使用的损失函数是MSE,即均方误差。但是均方误差对分类问题来说优缺点。

4.png

    使用更适合衡量两个概率分布差异的测量函数。其中,交叉熵(cross entropy)是一个常用的衡量方法:

5.png

    交叉熵的理解[https://www.zhihu.com/question/65288314]:



Tensorflow实现

  1. 获取数据集并将标签one-hot

from keras.datasets import fashion_mnist
import numpy as np

(x_train,y_train),(x_test,y_test)=fashion_mnist.load_data()

x_train=x_train.reshape(-1,784).astype('float32')/255.0
x_test=x_test.reshape(-1,784).astype('float32')/255.

y_train_onehot=np.zeros((y_train.shape[0],10))
y_test_onehot=np.zeros((y_test.shape[0],10))
for i,label in enumerate(y_train):
    y_train_onehot[i,label]=1
for i,label in enumerate(y_test):
    y_test_onehot[i,label]=1

    print(x_train.shape)
print(x_test.shape)
print(y_train.shape)
print(y_test.shape)

2.定义模型

%%time
import tensorflow as tf

num_inputs=784
num_outputs=10

#初始化模型变量
w = tf.Variable(initial_value=tf.random_normal(shape=(num_inputs,num_outputs),stddev=0.1,mean=0.))
b = tf.Variable(initial_value=tf.zeros(num_outputs))
#定义模型
x=tf.placeholder(tf.float32,shape=(None,num_inputs))
y_=tf.placeholder(tf.float32,shape=(None,num_outputs))
o=tf.matmul(x,w)+b

#定义softmax
#tf.nn.softmax()
y_exp=tf.exp(o)
exp_sum=tf.reduce_sum(y_exp,axis=1,keep_dims=True) #求和 保持维度不变
y=tf.divide(y_exp,exp_sum)


#定义正确率
correct_prediction=tf.equal(tf.argmax(y,1),tf.argmax(y_,1))
accuracy=tf.reduce_mean(tf.cast(correct_prediction,tf.float32))

#定义交叉熵损失函数
loss=-tf.reduce_mean(y_*tf.log(tf.clip_by_value(y,1e-10,1.0)))

#定义优化器
sgd=tf.train.GradientDescentOptimizer(0.001).minimize(loss)

3.训练模型

BATCH_SIZE=64
w_history=[]
b_history=[]
EPOCHS=30
BATCH_SIZE=128
pred=None

#生成对话,训练网络
with tf.Session() as sess:
    init_op=tf.global_variables_initializer() #初始化所有的Variable
    sess.run(init_op)
    
    for i in range(EPOCHS):
        xlen=x_train.shape[0]
        permutation = np.random.permutation(xlen)
        x_data = x_train[permutation]
        y_data = y_train_onehot[permutation]
        
        for j in range(xlen//BATCH_SIZE-1):
            x_batch=x_data[j*BATCH_SIZE:(j+1)*BATCH_SIZE,:]
            y_batch=y_data[j*BATCH_SIZE:(j+1)*BATCH_SIZE,:]
            sess.run(sgd,feed_dict={x:x_batch,y_:y_batch})
            
        acc=sess.run(accuracy,feed_dict={x:x_data[:1000],y_:y_data[:1000]})
        print('%d train acc:%f'%(i,acc))
    
    acc=sess.run(accuracy,feed_dict={x:x_test,y_:y_test_onehot})
    pred=sess.run(y,feed_dict={x:x_test[:30],y_:y_test_onehot[:30]})
    print('test acc:',str(acc))

4.显示测试结果

%matplotlib inline
import matplotlib.pyplot as plt
pred_map={0:"T-shirt",1:"Trouser",2:"Pullover",3:"Dress",4:"Coat",5:"Sandal",6:"Shirt",
            7:"Sneaker",8:"Bag",9:"Ankle boot"
         }
pred_index=np.argmax(pred,axis=1)
n=30
plt.figure(figsize=(24,8))
for i in range(n):
    ax=plt.subplot(3,10,i+1)
    plt.imshow(x_test[i].reshape(28,28))
    plt.gray()
    plt.title('data:'+pred_map[pred_index[i]]+'\n'+'pred:'+pred_map[y_test[i]])
    ax.get_xaxis().set_visible(False)
    ax.get_yaxis().set_visible(False)
plt.show()

6.png





参考文献

[1]阿斯顿·张(Aston Zhang) ,李沐(Mu Li),etc.动手学深度学习.http://zh.gluon.ai/chapter_deep-learning-basics/mlp.html 

首页 所有文章 机器人 计算机视觉 自然语言处理 机器学习 编程随笔 关于