softmax 回归的从零开始实现 讨论区


#85

很奇怪,我输出的test_data对应的accuracy是0.0267这样的值,按道理应该是在0.01附近的啊,有没有人和我有一样的问题,比较特别的是,如果用gluon的实现方式,这个值又变成0.15的样子


#86

def cross_entropy(yhat, y):
return - nd.pick(nd.log(yhat), y)
请问这个函数的pick的用法是什么?自己试了一下感觉和不加没有区别,都是输出nd.log(yhat)的值
另外前边加负号是基于什么考虑?


#87

您好。
在我这里使用 cpu 训练的时候,cpu 使用率只有 200% 多,这是正常情况吗?视频里面的 cpu 使用率好高的。
ps. 在服务器和自己的电脑上试了,都是这样。服务器 cpu 是 8 核的,自己电脑的 cpu 是 4 核的。


#88

你好,我想请教下 gluon 里面的参数初始化默认使用的是什么参数?

因为我发现把 gluon 初始化网络得到的参数,在不训练的情况下直接赋值到 scratch 版本的 w 和 b,scratch 版本的收敛速度变快,测试精度变高。我自己只查到了使用的是 Uniform 分布,还想知道一下相关的参数。


#89

MXNetError: [22:49:49] src/operator/contrib/…/elemwise_op_common.h:123: Check failed: assign(&dattr, (*vec)[i]) Incompatible attr in node at 1-th input: expected float64, got float32
出现上面的错误是什么原因呢?数据转成了float32,可是它说需要的是float64的,那怎么解决啊?求解答


#90

为什么这里会报错呢?


按照ipython的提示家里参数还是不行、。请问有人知道为啥么?谢谢


#91

pick好像是按照轴选择数组的元素组成新的数组,可能遇到复杂模型会需要吧


#92

是为了让数据都是在[0,1]之间,这样后面调学习率不会跟数据大小狠不一样调起来不一样

对每个batch取均值,通常是使得调学习率不要跟batch size耦合


#93

应该是模型初始值的原因吧

https://mxnet.incubator.apache.org/api/python/ndarray.html#mxnet.ndarray.pick

这个任务很小,所以看cpu使用率没有太多用。要么试试后面大的任务,或者试试mkl版本pip install mxnet-mkl

默认用的uniform,一般改一下确实会加速变化。

report到github issue上?https://github.com/apache/incubator-mxnet/issues

感觉是不是所有计算都在record()里?建议贴一些完整代码


#95

-- coding: utf-8 --

“”"
Created on Mon Jan 29 12:22:39 2018

@author:
"""

from mxnet import gluon
from mxnet import ndarray as nd

def transform(data,label):
return data.astype(‘float32’),label.astype(‘float32’)

通过gluon的data.vision模块自动下载这个数据。

mnist_train = gluon.data.vision.FashionMNIST(train=True,transform=transform)
mnist_test = gluon.data.vision.FashionMNIST(train=False,transform=transform)

data,label = mnist_train[0]

‘’’# 画图’’'
import matplotlib.pyplot as plt

def show_images(images):
n=images.shape[0]
_,figs = plt.subplots(1,n,figsize=(15,15))
for i in range(n):
figs[i].imshow(images[i].reshape((28,28)).asnumpy())
figs[i].axes.get_xaxis().set_visible(False)
figs[i].axes.get_yaxis().set_visible(False)
plt.show()

def get_text_labels(label):
text_labels=[‘t-shirt’, ‘trouser’, ‘pullover’, ‘dress,’, ‘coat’,
‘sandal’, ‘shirt’, ‘sneaker’, ‘bag’, ‘ankle boot’]
return [text_labels[int(i)] for i in label]

data,label =mnist_train[0:9]
show_images(data)
print(get_text_labels(label))

‘’‘数据读取’’'
batch_size = 256
train_data = gluon.data.DataLoader(mnist_train,batch_size,shuffle=True)
test_data = gluon.data.DataLoader(mnist_test,batch_size,shuffle=False)

‘’‘初始化模型参数’’'
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
"""定义模型

在线性回归教程里,我们只需要输出一个标量yhat使得尽可能的靠近目标值。
但在这里的分类里,我们需要属于每个类别的概率。这些概率需要值为正,而且加起来等于1.
而如果简单的使用 y^=Wx, 我们不能保证这一点。
一个通常的做法是通过softmax函数来将任意的输入归一化成合法的概率值。"""
def softmax(X):
exp = nd.exp(X)

假设exp是矩阵,这里对行进行求和,并要求保留axis 1,

就是返回(nrows,1)形状的矩阵

partition = exp.sum(axis=1,keepdims=True)
return exp/partition 

X = nd.random_normal(shape=(2,5))
X_prob = softmax(X)
print(X_prob)
print(X_prob.sum(axis=1))

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

‘’‘交叉熵损失函数’’'
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.
for data,label in data_iterator:
output = net(data)
acc+=accuracy(output,label)
return acc/len(data_iterator)

“”“训练”""

import sys
sys.path.append("…")
from utils import SGD
from mxnet import autograd
learning_rate =.1

for epoch in range(5):
train_loss = 0
train_acc = 0
for data,label in train_data:
with autograd.record():
output = net(data)
loss = cross_entropy(output,label)
loss.backward()
# 将梯度做平均,这样学习率会对batch size 不那么敏感
SGD(params,learning_rate/batch_size)
train_loss += nd.mean(loss).asscalar()
train_acc = accuracy(output,label)

test_acc = evaluate_accuracy(test_data,net)
print(“Epoch %d. loss: %f, Train acc %f, Test acc %f”%(epoch,train_loss/len(train_data),train_acc/len(train_data),test_acc))

‘’‘预测’’’

data,label = mnist_test[0:9]
show_images(data)
print(‘true labels’)
print(get_text_labels(label))

predicted_labels = net(data).argmax(axis=1)
print(“predicted labels”)

print(get_text_labels(predicted_labels.asnumpy()))


#96
Epoch 30. Loss: 0.723531, Train acc 0.803164, Test acc 0.803906
Epoch 31. Loss: 0.715727, Train acc 0.804721, Test acc 0.804980
Epoch 32. Loss: 0.709523, Train acc 0.805746, Test acc 0.807129
Epoch 33. Loss: 0.702957, Train acc 0.807574, Test acc 0.804395
Epoch 34. Loss: 0.695887, Train acc 0.807613, Test acc 0.804199

看到测试集准确率没有训练集高,我就放心了。因为看了沐大的视频都是测试集的高(虽然epoch=5),很不淡定,以为是mxnet的特性呢2333


#97

现在只看了2个。。


#98

你可能是前面的attach_grad()函数写错了;


#99

请问这里给梯度做平均,为什么会使得学习率对batch_size不敏感呢?


#100

因为计算出来的梯队和batch_size大小有关,将它除上一个batch_size能使得学习率对batch_size不敏感。实际上在使用GLUON写的时候用到trainer.step的时候也要传递batch_size


#101

如果随机种子设置1,会出现loss为nan的问题


#102

那可能是随机生成初始权重的时候数字太大了


#103

请教老师,我遇到两个问题:
问题1、定义 net(x)的时候
def net(x):
return softmax(nd.dot(x.reshape((-1, num_inputs)),w) +b)
老师视频说过,这个 reshape((-1, num_inputs)) -1的含义等同于 batch_size ,我就用 batch_size替换了 -1 系统运行会报错,错误代码如下:

[08:42:07] /Users/travis/build/dmlc/mxnet-distro/mxnet-build/dmlc-core/include/dmlc/logging.h:308: [08:42:07] src/ndarray/ndarray.cc:73: Check failed: shape_.Size() >= shape.Size() (12544 vs. 200704) NDArray.Reshape: target shape size is larger current shape

Stack trace returned 6 entries:
[bt] (0) 0 libmxnet.so 0x0000000103b03598 _ZN4dmlc15LogMessageFatalD2Ev + 40
[bt] (1) 1 libmxnet.so 0x0000000104b5bd7c _ZNK5mxnet7NDArray7ReshapeERKN4nnvm6TShapeE + 972
[bt] (2) 2 libmxnet.so 0x0000000104b5bee0 _ZN5mxnet7NDArray17ReshapeWithRecordERKN4nnvm6TShapeE + 48
[bt] (3) 3 libmxnet.so 0x00000001049f84a1 MXNDArrayReshape + 1841
[bt] (4) 4 _ctypes.cpython-36m-darwin.so 0x00000001022f51a7 ffi_call_unix64 + 79
[bt] (5) 5 Python 0x00007fff5bffe7a0 Python + 140730441918368

Traceback (most recent call last):
File “/Users/zyMao/Documents/Python/MXnet_Gluon/softmax-regression-scratch.py”, line 131, in
evaluate_accuracy(test_data, net)
File “/Users/zyMao/Documents/Python/MXnet_Gluon/softmax-regression-scratch.py”, line 122, in evaluate_accuracy
output = net(data)
File “/Users/zyMao/Documents/Python/MXnet_Gluon/softmax-regression-scratch.py”, line 111, in net
return softmax(nd.dot(x.reshape((batch_size, num_inputs)),w) +b) # 用 softmax(nd.dot(x.reshape((batch_size, num_inputs)),w) +b) 会报尺寸错误,选择输入 -1
File “/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/mxnet/ndarray/ndarray.py”, line 977, in reshape
ctypes.byref(handle)))
File “/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/mxnet/base.py”, line 146, in check_call
raise MXNetError(py_str(LIB.MXGetLastError()))
mxnet.base.MXNetError: [08:42:07] src/ndarray/ndarray.cc:73: Check failed: shape
.Size() >= shape.Size() (12544 vs. 200704) NDArray.Reshape: target shape size is larger current shape

Stack trace returned 6 entries:
[bt] (0) 0 libmxnet.so 0x0000000103b03598 _ZN4dmlc15LogMessageFatalD2Ev + 40
[bt] (1) 1 libmxnet.so 0x0000000104b5bd7c _ZNK5mxnet7NDArray7ReshapeERKN4nnvm6TShapeE + 972
[bt] (2) 2 libmxnet.so 0x0000000104b5bee0 _ZN5mxnet7NDArray17ReshapeWithRecordERKN4nnvm6TShapeE + 48
[bt] (3) 3 libmxnet.so 0x00000001049f84a1 MXNDArrayReshape + 1841
[bt] (4) 4 _ctypes.cpython-36m-darwin.so 0x00000001022f51a7 ffi_call_unix64 + 79
[bt] (5) 5 Python 0x00007fff5bffe7a0 Python + 140730441918368

问题2: 属于 SGD(params, learning_rate/batch_size) 的 learning_rate/batch_size
为什么需要做 learning_rate/batch_size 这个相除?用这个相除的数据传入SGD后,我的Loss: nan。


我将其修改成为 learning_rate ,Loss 正常。

注明:两次测试learning_rate=0.0005


#104

老师您好,我是初学者,我在做softmax-regression-scratch 参数调整时遇到两个问题:
问题1:
在调整learning_rate 的时候,我们怎么确认这个learning_rate 是较优呢?
是: 初始的Loss 越小,Train 和 Test 越大越好吗?

问题2:
在设置 learning_rate = 0.4 和 rang(100)

迭代到45次后,为什么Loss: nan 了?是过拟合了吗?



#106

关于batch size 在定义net时 reshape成 -1 的问题

之前看视频沐神上课说-1可以改成batch size,后来试了下发现改成batch size会出现问题。看到有小伙伴解释是因为最后一组训练的数据小于batch size而导致报错,当时想了想觉得有道理就没管了。后来好奇心驱使我试了下调整batch size来验证这个观点。于是有了接下来的测试,如图:

b1e1

我把batch size设为1, 即打印出整个train data的大小,发现这个训练数据集的大小是60000。所以如果我们将batch size设为256,并把X reshape成(256, 784)时,除不尽嘛,所以肯定有问题。然后我把X reshape重新设置成-1, 看看系统到底怎么处理这个问题。结果如图:

b256-i235

也就是说,在这个epoch中,总共有235次迭代,前234次X的size是256, 最后一次是96,即 256 × 234 + 96 = 60000 。很好,按理一切都结束了,能解释通了。但我手痒,把batch size 调到100 ,X reshape成batch size大小,迭代600次,没问题,size 调到200, 迭代300次,很好,batch size 调到300,

报错如上图,当时我就蒙笔了。迭代200次,没问题啊,看Error上提到reshape的问题,于是我查了一波API,也没啥问题。自己动手reshape 下,

可以reshape。然后把net中 reshape 的batch size改回-1重新跑小训练,完全没问题。我当时就纳闷了,于是我回过头仔细去看具体的问题描述,发现报错是在test_acc那。我似乎明白了什么,

test data size

于是我把train data 改成 test data跑一遍,果然test data 总共是 10000, 并不能除尽300, 但是可以除尽100和200。也就是我们在定义net的时候要想到数据集在reshape之后要能够同时适用训练集和测试集。

总结,训练集的size与测试集的size一般不一样,所以如果将X reshape batch_size大小且不出错,必须训练集的size与测试集的size都能够除尽这个batch_size。所以不如设成-1省事 :slight_smile: 。最后用沐神的话说就是: Get hands dirty. 遇到问题多去动手试,keep careful and carry on。