大大前天写了一个神经网络,跑了三天,到大前天重启电脑的时候才发现状态保存没写好,当时以为是有参数变量忘记存了,或者是存储的时候操作错误,查错查了三个小时都没查出问题(还发了个帖子: https://www.v2ex.com/t/739076 ),心情很差,不想调了,就把代码放在一边,跑去做别的事了,每天时不时看看代码,但是怎么看都感觉没问题。
刚刚终于开始单步调试,一调就发现问题了。
问题相当隐蔽:
我的网络输入的是文本,预处理的时候先做了一个字符表:
chars = set(open('...txt').read())
self.char_to_ix = { ch:i for i,ch in enumerate(chars) }
这个字符表看起来每次运行都是一样的,但是实际上不是。
不知道为什么,enumerate(set(...))
这个操作每次得到的内容顺序是随机的。大家可以去自己的 Python 里黏贴这一句试试:
{ ch:i for i,ch in enumerate(set('我爱你中国')) }
比比如我第一次运行,结果是:
{'国': 0, '爱': 1, '中': 2, '你': 3, '我': 4}
重启 Python(必须重启),再运行,结果变为:
{'爱': 0, '中': 1, '你': 2, '我': 3, '国': 4}
就是因为这个简单的错误,一旦重启程序,虽然网络参数都保存得很好,但是因为数据源变了,所以训练得从头开始。
最令人沮丧的是,我本来以为这是一个很难调试的错误,所以一直没有去动它;但是真正一开始调试,又发现这个问题如此简单————随后发现,我只是懒而已(= =)
不管怎么样,enumerate(set(...))
的这个行为都很奇怪。我简单翻看了一下文档,但是没见到有关解释。打算去 Stackoverflow 问问。
这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。
V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。
V2EX is a community of developers, designers and creative people.