<jupyter_start><jupyter_text>softmax如何使用多类逻辑回归进行多类分类。这个模型跟线性回归的主要区别在于输出节点从一个变成了多个。![](../img/simple-softmax-net.png)<jupyter_code>import mxnet as mx

# Fixing the random seed
mx.random.seed(42)

mnist = mx.test_utils.get_mnist()
batch_size = 5
train_data = mx.io.NDArrayIter(mnist['train_data'], mnist['train_label'], batch_size, shuffle=True)
val_data = mx.io.NDArrayIter(mnist['test_data'], mnist['test_label'], batch_size)
num_trains = 0

for batch in train_data:
    #print batch.data[0].shape
    num_trains += len(batch.data[0])
    #print batch.label[0].shape
    #break
num_vals = 0
for batch in val_data:
    num_vals += len(batch.data[0])
print num_vals
print num_trains
from mxnet import ndarray as nd
from mxnet import autograd as ag
def softmax(X):
    X_max = X.max(axis=1, keepdims=True)
    #print X_max
    X = X - X_max
    exp = nd.exp(X)
    partition = exp.sum(axis=1, keepdims=True)
    return exp / partition
num_inputs = 784
num_outputs = 10

W = nd.random_normal(shape=(num_inputs, num_outputs))
b = nd.random_normal(shape=num_outputs)

params = [W, b]
for param in params:
    param.attach_grad()
def net(X):
    #print "here"
    X_dense = X.reshape((-1,num_inputs))
    output = nd.dot(X_dense, W) + b
    #print X_dense
    #print W
    return softmax(output)
def cross_entropy(yhat, y):
    return - nd.pick(nd.log(yhat), y)
def accuracy(output, label):
    return nd.mean(output.argmax(axis=1)==label).asscalar()
def evaluate_accuracy(data_iterator, net):
    acc = 0.
    #total_length = 0
    for batch in data_iterator:
        data = batch.data[0]
        label = batch.label[0]
        output = net(data)
        acc += accuracy(output, label)
        #total_length += len(data)
    #print total_length
    #return acc / len(data_iterator)
    return acc / num_vals
def SGD(params, learning_rate):
    for param in params:
        param -= learning_rate * param.grad
learning_rate = .01

epochs = 20
for epoch in range(epochs):
    train_loss = 0.
    train_acc = 0.
    train_data.reset()
    val_data.reset()
    for batch in train_data:
        data = batch.data[0]
        label = batch.label[0]
        with ag.record():
            output = net(data)
            #break
            loss = cross_entropy(output, label)
        loss.backward()
        #print loss
        # 将梯度做平均，这样学习率会对batch size不那么敏感
        SGD(params, learning_rate/batch_size)

        train_loss += nd.mean(loss).asscalar()
        train_acc += accuracy(output, label)

    test_acc = evaluate_accuracy(val_data, net)
    print("Epoch %d. Loss: %f, Train acc %f, Test acc %f" % (
        epoch, train_loss/num_trains, train_acc/num_trains, test_acc))<jupyter_output>Epoch 0. Loss: 0.367585, Train acc 0.138880, Test acc 0.164740
Epoch 1. Loss: 0.161679, Train acc 0.166410, Test acc 0.171480
Epoch 2. Loss: 0.132810, Train acc 0.171347, Test acc 0.174320
Epoch 3. Loss: 0.117867, Train acc 0.173697, Test acc 0.175920
Epoch 4. Loss: 0.108286, Train acc 0.175280, Test acc 0.176920
Epoch 5. Loss: 0.101441, Train acc 0.176340, Test acc 0.177620
Epoch 6. Loss: 0.096214, Train acc 0.177210, Test acc 0.178280
Epoch 7. Loss: 0.092037, Train acc 0.177883, Test acc 0.178660
Epoch 8. Loss: 0.088591, Train acc 0.178580, Test acc 0.178880
{'fraction_non_alphanumeric': 0.11891558841651263, 'fraction_numerical': 0.07024029574861368, 'mean_word_length': 3.2611548556430447, 'pattern_counts': {'":': 0, '<': 4, '<?xml version=': 0, '>': 4, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '1', 'dir': 'jupyter-structured-clean-dedup', 'id': '454448', 'license': 'MIT', 'n_tokens_mistral': 1390, 'n_tokens_neox': 1271, 'n_words': 309, 'path': 'lesson2_softmax/.ipynb_checkpoints/2.softmax-mxnet-checkpoint.ipynb', 'repo_name': 'myotheone/machine_learning_101', 'size': '3246'}