神经网络之softmax回归(图片识别)

  softmax回归是Logistic回归在多分类问题上的推广,一般用于神经网络的输出层,此时输出层叫做softmax层。这里用softmax回归做一个简单的神经网络,利用该模型对衣服鞋子进行分类,数据采用d2lzh中的Fashion-MNIST数据集

softmax函数

这个函数可以将一个向量(x1,x2,...,xK)映射为一个概率分布(z1,z2,...,zK),它将数据的范围映射到(0,1)区间:

神经网络之softmax回归(图片识别)_第1张图片

对今天的图片分类来说,一个图片数据根据神经网络计算可以得到1*10大小的向量(为什么是10,因为总共分成10个类型),然后将这个向量带入上述公式,就可以得到这个图片属于每个类型的可能性大小,后面会讲如何根据这个可能性的向量构造相应的损失函数。

代码


%matplotlib inline
import d2lzh as d2l
from mxnet import autograd, nd

batch_size = 256
train_iter, test_iter = d2l.load_data_fashion_mnist(batch_size)#将数据集按batch_size大小分为256一份

#看看这些图片长什么样
for i,j in train_iter:
    break
d2l.show_fashion_mnist(i[0:9], d2l.get_fashion_mnist_labels(j.asnumpy())[0:9])

  

  解释下怎么生成这些图片,首先从train_iter训练集中提取一份数据,通过for循环加break跳出操作,这一份数据里面有256张图片,此时i,j里面分别是训练集中的一部分输入和输出,i[0:9]表示取10张图片数据,d2l.get_fashion_mnist_labels(j.asnumpy())的作用是将j转化为数组后(原先j是张量,里面是范围在0-9的整数,标签为10种类型),然后将数组中的数字转化为对应的物品名称,show_fashion_mnist(放入数据集张量,放入名称列表)。

好,训练集测试集都有了,正式开始

初始化参数

num_inputs = 784
num_outputs = 10

W = nd.random.normal(scale=0.01, shape=(num_inputs, num_outputs))
b = nd.zeros(num_outputs)

W.attach_grad()
b.attach_grad()

因为图片是28*28像素的,后面会通过reshape转为1*784的,固这里w的shape设为784*10,随机生成服从(0,0.01)正态分布的数据,然后W.attach_grad(),b.attach_grad()给参数申请内存求导,这样根据损失函数就可以更新参数了,必加。

def softmax(X):
    X_exp = X.exp()
    partition = X_exp.sum(axis=1, keepdims=True)
    return X_exp / partition  # 这里应用了广播机制

def net(X):
    return softmax(nd.dot(X.reshape((-1, num_inputs)), W) + b)

def cross_entropy(y_hat, y):
    return -nd.pick(y_hat, y).log()

def evaluate_accuracy(data_iter, net):
    acc_sum, n = 0.0, 0
    for X, y in data_iter:
        y = y.astype('float32')
        acc_sum += (net(X).argmax(axis=1) == y).sum().asscalar()
        n += y.size
    return acc_sum / n

定义好softmax函数和net函数,softmax函数公式上文已讲,然后net函数是根据w,b计算出1*10的向量然后根据softmax函数转化为对应的概率大小,这里通过reshape来将28*28的像素矩阵转化为1*784向量,cross_entropy计算损失函数,其实就是根据图片实际对应的类型,然后找到类型对应的模型计算出来的概率大小,对这个概率log下然后加负数,evaluate_accuracy计算模型的准确率

正式训练

num_epochs, lr = 5, 0.1

# 本函数已保存在d2lzh包中方便以后使用
def train_ch3(net, train_iter, test_iter, loss, num_epochs, batch_size,
              params=None, lr=None, trainer=None):
    for epoch in range(num_epochs):
        train_l_sum, train_acc_sum, n = 0.0, 0.0, 0
        for X, y in train_iter:
            with autograd.record():
                y_hat = net(X)
                l = loss(y_hat, y).sum()
            l.backward()
            if trainer is None:
                d2l.sgd(params, lr, batch_size)
            else:
                trainer.step(batch_size)  # “softmax回归的简洁实现”一节将用到
            y = y.astype('float32')
            train_l_sum += l.asscalar()
            train_acc_sum += (y_hat.argmax(axis=1) == y).sum().asscalar()
            n += y.size
        test_acc = evaluate_accuracy(test_iter, net)
        print('epoch %d, loss %.4f, train acc %.3f, test acc %.3f'
              % (epoch + 1, train_l_sum / n, train_acc_sum / n, test_acc))

train_ch3(net, train_iter, test_iter, cross_entropy, num_epochs, batch_size,
          [W, b], lr)

  这里设置num_epochs,lr 分别等于5,0.1代表总共迭代五次,学习速率为0.1

  依次train_ch3函数中分别放入net模型计算方式,训练集和测试集,cross_entropy损失函数,循环次数,小批量样本数,权重偏差,学习速率

结果如下:

神经网络之softmax回归(图片识别)_第2张图片

看着迭代五次后结果好像没什么变化,是因为我做过好几次了,权重一直在更新,所以准确率什么的都增加不大

for X, y in test_iter:
    break

true_labels = d2l.get_fashion_mnist_labels(y.asnumpy())
pred_labels = d2l.get_fashion_mnist_labels(net(X).argmax(axis=1).asnumpy())
titles = [true + '\n' + pred for true, pred in zip(true_labels, pred_labels)]

d2l.show_fashion_mnist(X[0:9], titles[0:9])

看看图片效果

可以看到4,5,6件分类错误,其他正确,效果还不错70%的准确率

以上就是softmax回归的一个代码实现,有任何问题,欢迎讨论

你可能感兴趣的:(神经网络之softmax回归(图片识别))