我有一个问题,我正在尝试为Tic-Tac-Toe创建一个神经网络.但是,出于某种原因,训练神经网络会导致它为任何给定的输入产生几乎相同的输出.
我确实看过人工神经网络基准测试,但我的网络实现是针对每个神经元具有相同激活功能的神经元构建的,即没有恒定的神经元.
为了确保问题不仅仅是由于我选择的训练集(1218板状态和遗传算法产生的移动),我试图训练网络重现XOR.使用逻辑激活函数.我没有使用导数,而是将误差乘以,output*(1-output)
因为有些消息来源暗示这相当于使用导数.我可以将Haskell源代码放在HPaste上,但看起来有点尴尬.网络有3层:第一层有2个输入和4个输出,第二层有4个输入和1个输出,第三层有1个输出.在第二层中增加到4个神经元没有帮助,并且在第一层中也没有增加到8个输出.
然后,我根据http://hebb.mit.edu/courses/9.641/2002/lectures/lecture04.pdf手动计算错误,网络输出,偏差更新和重量更新,以确保没有错误代码的那些部分(没有,但我可能会再做一次以确保).因为我正在使用批量训练,所以我没有乘以x
等式(4).我正在添加重量变化,但http://www.faqs.org/faqs/ai-faq/neural-nets/part2/section-2.html建议减去它.
即使在这个简化的网络中,问题仍然存在.例如,这些是500个批次培训和增量培训时期之后的结果.
Input |Target|Output (Batch) |Output(Incremental)
[1.0,1.0]|[0.0] |[0.5003781562785173]|[0.5009731800870864]
[1.0,0.0]|[1.0] |[0.5003740346965251]|[0.5006347214672715]
[0.0,1.0]|[1.0] |[0.5003734471544522]|[0.500589332376345]
[0.0,0.0]|[0.0] |[0.5003674110937019]|[0.500095157458231]
Run Code Online (Sandbox Code Playgroud)
减去而不是添加产生相同的问题,除了一切都是0.99而不是0.50的东西.5000个时期产生相同的结果,除了批量训练的网络每个案例返回0.5.(哎呀,即使是10000个时代也没有用于批量训练.)
有什么一般可以产生这种行为?
此外,我查看了增量训练的中间误差,虽然隐藏/输入层的输入变化,但输出神经元的误差始终为+/- 0.12.对于批量训练,错误增加,但非常缓慢,错误都非常小(x10 ^ -7).不同的初始随机权重和偏差也没有差别.
请注意,这是一个学校项目,所以提示/指南会更有帮助.虽然重新发明轮子和制作我自己的网络(用一种我不太熟悉的语言!)是一个可怕的想法,我觉得这对学校项目更合适(所以我知道发生了什么......理论上,至少.我的学校似乎没有计算机科学老师).
编辑:两层,一个输入层,两个输入到8个输出,一个输出层,8个输入到1个输出,产生大致相同的结果:每个训练案例0.5 +/- 0.2(左右).我也在玩pyBrain,看看是否有任何网络结构可行.
编辑2:我使用的学习率为0.1.很抱歉忘了这件事.
编辑3:Pybrain的"trainUntilConvergence"也没有让我成为一个训练有素的网络,但20000个时代确实如此,隐藏层中有16个神经元.10000个时代和4个神经元,不是那么多,而是接近.所以,在Haskell中,输入层有2个输入和2个输出,隐藏层有2个输入和8个输出,输出层有8个输入和1个输出......我得到了10000个时期的相同问题.并拥有20000个时代.
编辑4:我根据上面的MIT PDF再次手动运行网络,并且值匹配,因此代码应该是正确的,除非我误解了这些方程式.
我的一些源代码位于http://hpaste.org/42453/neural_network__not_working ; 我正在努力清理我的代码并将其放在Github(而不是私有的Bitbucket)存储库中.
所有相关的源代码现在都在https://github.com/l33tnerd/hsann.
我正在尝试创建一个函数,使用遗传算法递归地播放所有可能的井字游戏,然后返回(胜利,损失,关系)元组.但是,当调用时,下面的函数总是溢出堆栈:
scoreOne :: UnscoredPlayer -> [String] -> ScoredPlayer
scoreOne player boards = ScoredPlayer (token player) (chromosome player) (evaluateG $! testPlayer player boards)
...
let results = map (\x->scoreOne x boards) players
print (maximum results)
Run Code Online (Sandbox Code Playgroud)
哪里players
是染色体列表.只有1名玩家不会发生溢出,但有两次发生.
编辑:如果以下列方式调用该函数,它不会溢出堆栈.
let results = map (\player -> evaluateG (testPlayer player boards)) players
print (maximum results)
Run Code Online (Sandbox Code Playgroud)
但是,以下方式会溢出堆栈.
let results = map (\player -> ScoredPlayer (token player) (chromosome player) (evaluateG $! testPlayer player boards)) players
Run Code Online (Sandbox Code Playgroud)
作为参考,ScoredPlayer
定义为(字符串是玩家令牌,[Int]是染色体,Float是得分):
data ScoredPlayer = ScoredPlayer String …
Run Code Online (Sandbox Code Playgroud) 代码优先:
class A(object):
def foo(self):
self.foo = 'foo'
def bar(self):
self.bar = 'bar'
cls_dict = dict(A.__dict__) #not empty
a = A()
a_dict = dict(a.__dict__) #empty, why?
Run Code Online (Sandbox Code Playgroud) 比如说,在Yesod/Persistent中,我有这样的模型设置:
User
ident Text
password Text Maybe
UniqueUser ident
Question
title Text
asker UserId Eq
Run Code Online (Sandbox Code Playgroud)
我有一个Question
s 列表,并希望检索相应的User
s 列表.我该怎么做呢?
我考虑过加入,但这些是一对多的,而不是一对一的(我想它没关系,但我想要一个更简单的解决方案).手动进行连接也是一种选择,但我担心性能 - 我有
questions <- runDB $ selectList [QuestionTitle !=. ""] [LimitTo 10]
let askerIds = map (\(Entity _ q) -> questionAsker q) questions
askers <- sequence $ map (runDB . get) askerIds
let questionsAndAskers = zip questions askers
Run Code Online (Sandbox Code Playgroud)
但是我担心runDB
在map
(不会为每个用户单独向数据库发出请求?)
是否有更好/更惯用的方法来实现这一目标?