- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
编辑2:
新训练集...
输入:
[
[0.0, 0.0],
[0.0, 1.0],
[0.0, 2.0],
[0.0, 3.0],
[0.0, 4.0],
[1.0, 0.0],
[1.0, 1.0],
[1.0, 2.0],
[1.0, 3.0],
[1.0, 4.0],
[2.0, 0.0],
[2.0, 1.0],
[2.0, 2.0],
[2.0, 3.0],
[2.0, 4.0],
[3.0, 0.0],
[3.0, 1.0],
[3.0, 2.0],
[3.0, 3.0],
[3.0, 4.0],
[4.0, 0.0],
[4.0, 1.0],
[4.0, 2.0],
[4.0, 3.0],
[4.0, 4.0]
]
输出:
[
[0.0],
[0.0],
[0.0],
[0.0],
[0.0],
[0.0],
[0.0],
[0.0],
[0.0],
[0.0],
[0.0],
[0.0],
[0.0],
[0.0],
[0.0],
[0.0],
[0.0],
[0.0],
[1.0],
[1.0],
[0.0],
[0.0],
[0.0],
[1.0],
[1.0]
]
编辑1:
我已经用我的最新代码更新了问题。我修复了一些小问题,但在网络学习后,我仍然为所有输入组合获得相同的输出。
这里是反向传播算法的解释:Backprop algorithm
是的,这是一项作业,要在一开始就明确这一点。
我应该在一个简单的神经网络上实现一个简单的反向传播算法。
我选择 Python 作为此任务的首选语言,并且我选择了这样的神经网络:
3层:1个输入层,1个隐藏层,1个输出层:
O O
O
O O
在输入神经元上都有一个整数,在输出神经元上有 1 或 0。
这是我的整个实现(有点长)。在下面,我将选择较短的相关片段,我认为错误可能位于:
import os
import math
import Image
import random
from random import sample
#------------------------------ class definitions
class Weight:
def __init__(self, fromNeuron, toNeuron):
self.value = random.uniform(-0.5, 0.5)
self.fromNeuron = fromNeuron
self.toNeuron = toNeuron
fromNeuron.outputWeights.append(self)
toNeuron.inputWeights.append(self)
self.delta = 0.0 # delta value, this will accumulate and after each training cycle used to adjust the weight value
def calculateDelta(self, network):
self.delta += self.fromNeuron.value * self.toNeuron.error
class Neuron:
def __init__(self):
self.value = 0.0 # the output
self.idealValue = 0.0 # the ideal output
self.error = 0.0 # error between output and ideal output
self.inputWeights = []
self.outputWeights = []
def activate(self, network):
x = 0.0;
for weight in self.inputWeights:
x += weight.value * weight.fromNeuron.value
# sigmoid function
if x < -320:
self.value = 0
elif x > 320:
self.value = 1
else:
self.value = 1 / (1 + math.exp(-x))
class Layer:
def __init__(self, neurons):
self.neurons = neurons
def activate(self, network):
for neuron in self.neurons:
neuron.activate(network)
class Network:
def __init__(self, layers, learningRate):
self.layers = layers
self.learningRate = learningRate # the rate at which the network learns
self.weights = []
for hiddenNeuron in self.layers[1].neurons:
for inputNeuron in self.layers[0].neurons:
self.weights.append(Weight(inputNeuron, hiddenNeuron))
for outputNeuron in self.layers[2].neurons:
self.weights.append(Weight(hiddenNeuron, outputNeuron))
def setInputs(self, inputs):
self.layers[0].neurons[0].value = float(inputs[0])
self.layers[0].neurons[1].value = float(inputs[1])
def setExpectedOutputs(self, expectedOutputs):
self.layers[2].neurons[0].idealValue = expectedOutputs[0]
def calculateOutputs(self, expectedOutputs):
self.setExpectedOutputs(expectedOutputs)
self.layers[1].activate(self) # activation function for hidden layer
self.layers[2].activate(self) # activation function for output layer
def calculateOutputErrors(self):
for neuron in self.layers[2].neurons:
neuron.error = (neuron.idealValue - neuron.value) * neuron.value * (1 - neuron.value)
def calculateHiddenErrors(self):
for neuron in self.layers[1].neurons:
error = 0.0
for weight in neuron.outputWeights:
error += weight.toNeuron.error * weight.value
neuron.error = error * neuron.value * (1 - neuron.value)
def calculateDeltas(self):
for weight in self.weights:
weight.calculateDelta(self)
def train(self, inputs, expectedOutputs):
self.setInputs(inputs)
self.calculateOutputs(expectedOutputs)
self.calculateOutputErrors()
self.calculateHiddenErrors()
self.calculateDeltas()
def learn(self):
for weight in self.weights:
weight.value += self.learningRate * weight.delta
def calculateSingleOutput(self, inputs):
self.setInputs(inputs)
self.layers[1].activate(self)
self.layers[2].activate(self)
#return round(self.layers[2].neurons[0].value, 0)
return self.layers[2].neurons[0].value
#------------------------------ initialize objects etc
inputLayer = Layer([Neuron() for n in range(2)])
hiddenLayer = Layer([Neuron() for n in range(100)])
outputLayer = Layer([Neuron() for n in range(1)])
learningRate = 0.5
network = Network([inputLayer, hiddenLayer, outputLayer], learningRate)
# just for debugging, the real training set is much larger
trainingInputs = [
[0.0, 0.0],
[1.0, 0.0],
[2.0, 0.0],
[0.0, 1.0],
[1.0, 1.0],
[2.0, 1.0],
[0.0, 2.0],
[1.0, 2.0],
[2.0, 2.0]
]
trainingOutputs = [
[0.0],
[1.0],
[1.0],
[0.0],
[1.0],
[0.0],
[0.0],
[0.0],
[1.0]
]
#------------------------------ let's train
for i in range(500):
for j in range(len(trainingOutputs)):
network.train(trainingInputs[j], trainingOutputs[j])
network.learn()
#------------------------------ let's check
for pattern in trainingInputs:
print network.calculateSingleOutput(pattern)
现在的问题是,在学习之后,网络似乎为所有输入组合返回一个非常接近 0.0 的 float ,即使是那些应该接近 1.0 的组合也是如此。
我在 100 个循环中训练网络,在每个循环中我都这样做:
对于训练集中的每组输入:
然后我根据学习率和累积增量调整权重。
这是我的神经元激活函数:
def activationFunction(self, network):
"""
Calculate an activation function of a neuron which is a sum of all input weights * neurons where those weights start
"""
x = 0.0;
for weight in self.inputWeights:
x += weight.value * weight.getFromNeuron(network).value
# sigmoid function
self.value = 1 / (1 + math.exp(-x))
这是我计算增量的方式:
def calculateDelta(self, network):
self.delta += self.getFromNeuron(network).value * self.getToNeuron(network).error
这是我的算法的一般流程:
for i in range(numberOfIterations):
for k,expectedOutput in trainingSet.iteritems():
coordinates = k.split(",")
network.setInputs((float(coordinates[0]), float(coordinates[1])))
network.calculateOutputs([float(expectedOutput)])
network.calculateOutputErrors()
network.calculateHiddenErrors()
network.calculateDeltas()
oldWeights = network.weights
network.adjustWeights()
network.resetDeltas()
print "Iteration ", i
j = 0
for weight in network.weights:
print "Weight W", weight.i, weight.j, ": ", oldWeights[j].value, " ............ Adjusted value : ", weight.value
j += j
输出的最后两行是:
0.552785449458 # this should be close to 1
0.552785449458 # this should be close to 0
它实际上返回所有输入组合的输出数字。
我错过了什么吗?
最佳答案
看起来你得到的几乎是神经元的初始状态(接近self.idealValue
)。也许您不应该在提供实际数据之前初始化此神经元?
编辑:好的,我仔细查看了代码并稍微简化了它(将在下面发布简化版本)。基本上您的代码有两个小错误(看起来像是您刚刚忽略的事情),但这会导致网络肯定无法正常工作。
显然,这两个问题中的任何一个都会导致功能失调的网络。
一旦更正,它就可以工作(好吧,它在我的简化版代码中工作)。
错误不容易发现,因为初始代码太复杂了。在引入新类或新方法之前,您应该三思而后行。没有创建足够的方法或类会使代码难以阅读和维护,但创建太多可能会使代码更难阅读和维护。你必须找到合适的平衡点。我个人找到这种平衡的方法是遵循 code smells和重构技术,无论它们引导我到哪里。有时添加方法或创建类,有时删除它们。它当然不完美,但这对我有用。
以下是应用一些重构后我的代码版本。我花了大约一个小时更改您的代码,但始终保持其功能相同。我认为这是一个很好的重构练习,因为最初的代码读起来真的很糟糕。重构后,只用了 5 分钟就发现了问题。
import os
import math
"""
A simple backprop neural network. It has 3 layers:
Input layer: 2 neurons
Hidden layer: 2 neurons
Output layer: 1 neuron
"""
class Weight:
"""
Class representing a weight between two neurons
"""
def __init__(self, value, from_neuron, to_neuron):
self.value = value
self.from_neuron = from_neuron
from_neuron.outputWeights.append(self)
self.to_neuron = to_neuron
to_neuron.inputWeights.append(self)
# delta value, this will accumulate and after each training cycle
# will be used to adjust the weight value
self.delta = 0.0
class Neuron:
"""
Class representing a neuron.
"""
def __init__(self):
self.value = 0.0 # the output
self.idealValue = 0.0 # the ideal output
self.error = 0.0 # error between output and ideal output
self.inputWeights = [] # weights that end in the neuron
self.outputWeights = [] # weights that starts in the neuron
def activate(self):
"""
Calculate an activation function of a neuron which is
a sum of all input weights * neurons where those weights start
"""
x = 0.0;
for weight in self.inputWeights:
x += weight.value * weight.from_neuron.value
# sigmoid function
self.value = 1 / (1 + math.exp(-x))
class Network:
"""
Class representing a whole neural network. Contains layers.
"""
def __init__(self, layers, learningRate, weights):
self.layers = layers
self.learningRate = learningRate # the rate at which the network learns
self.weights = weights
def training(self, entries, expectedOutput):
for i in range(len(entries)):
self.layers[0][i].value = entries[i]
for i in range(len(expectedOutput)):
self.layers[2][i].idealValue = expectedOutput[i]
for layer in self.layers[1:]:
for n in layer:
n.activate()
for n in self.layers[2]:
error = (n.idealValue - n.value) * n.value * (1 - n.value)
n.error = error
for n in self.layers[1]:
error = 0.0
for w in n.outputWeights:
error += w.to_neuron.error * w.value
n.error = error
for w in self.weights:
w.delta += w.from_neuron.value * w.to_neuron.error
def updateWeights(self):
for w in self.weights:
w.value += self.learningRate * w.delta
def calculateSingleOutput(self, entries):
"""
Calculate a single output for input values.
This will be used to debug the already learned network after training.
"""
for i in range(len(entries)):
self.layers[0][i].value = entries[i]
# activation function for output layer
for layer in self.layers[1:]:
for n in layer:
n.activate()
print self.layers[2][0].value
#------------------------------ initialize objects etc
neurons = [Neuron() for n in range(5)]
w1 = Weight(-0.79, neurons[0], neurons[2])
w2 = Weight( 0.51, neurons[0], neurons[3])
w3 = Weight( 0.27, neurons[1], neurons[2])
w4 = Weight(-0.48, neurons[1], neurons[3])
w5 = Weight(-0.33, neurons[2], neurons[4])
w6 = Weight( 0.09, neurons[3], neurons[4])
weights = [w1, w2, w3, w4, w5, w6]
inputLayer = [neurons[0], neurons[1]]
hiddenLayer = [neurons[2], neurons[3]]
outputLayer = [neurons[4]]
learningRate = 0.3
network = Network([inputLayer, hiddenLayer, outputLayer], learningRate, weights)
# just for debugging, the real training set is much larger
trainingSet = [([0.0,0.0],[0.0]),
([1.0,0.0],[1.0]),
([2.0,0.0],[1.0]),
([0.0,1.0],[0.0]),
([1.0,1.0],[1.0]),
([2.0,1.0],[0.0]),
([0.0,2.0],[0.0]),
([1.0,2.0],[0.0]),
([2.0,2.0],[1.0])]
#------------------------------ let's train
for i in range(100): # training iterations
for entries, expectedOutput in trainingSet:
network.training(entries, expectedOutput)
network.updateWeights()
#network has learned, let's check
network.calculateSingleOutput((1, 0)) # this should be close to 1
network.calculateSingleOutput((0, 0)) # this should be close to 0
顺便说一句,还有第三个问题我没有改正(但很容易改正)。如果 x 太大或太小(> 320 或 < -320)math.exp()
将引发异常。如果您申请训练迭代,比如几千次,就会发生这种情况。我看到最简单的纠正方法是检查 x 的值,如果它太大或太小,则根据情况将 Neuron 的值设置为 0 或 1,这是极限值。
关于python - 帮助我在 Python 中实现反向传播,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3988238/
背景: 我最近一直在使用 JPA,我为相当大的关系数据库项目生成持久层的轻松程度给我留下了深刻的印象。 我们公司使用大量非 SQL 数据库,特别是面向列的数据库。我对可能对这些数据库使用 JPA 有一
我已经在我的 maven pom 中添加了这些构建配置,因为我希望将 Apache Solr 依赖项与 Jar 捆绑在一起。否则我得到了 SolarServerException: ClassNotF
interface ITurtle { void Fight(); void EatPizza(); } interface ILeonardo : ITurtle {
我希望可用于 Java 的对象/关系映射 (ORM) 工具之一能够满足这些要求: 使用 JPA 或 native SQL 查询获取大量行并将其作为实体对象返回。 允许在行(实体)中进行迭代,并在对当前
好像没有,因为我有实现From for 的代码, 我可以转换 A到 B与 .into() , 但同样的事情不适用于 Vec .into()一个Vec . 要么我搞砸了阻止实现派生的事情,要么这不应该发
在 C# 中,如果 A 实现 IX 并且 B 继承自 A ,是否必然遵循 B 实现 IX?如果是,是因为 LSP 吗?之间有什么区别吗: 1. Interface IX; Class A : IX;
就目前而言,这个问题不适合我们的问答形式。我们希望答案得到事实、引用资料或专业知识的支持,但这个问题可能会引发辩论、争论、投票或扩展讨论。如果您觉得这个问题可以改进并可能重新打开,visit the
我正在阅读标准haskell库的(^)的实现代码: (^) :: (Num a, Integral b) => a -> b -> a x0 ^ y0 | y0 a -> b ->a expo x0
我将把国际象棋游戏表示为 C++ 结构。我认为,最好的选择是树结构(因为在每个深度我们都有几个可能的移动)。 这是一个好的方法吗? struct TreeElement{ SomeMoveType
我正在为用户名数据库实现字符串匹配算法。我的方法采用现有的用户名数据库和用户想要的新用户名,然后检查用户名是否已被占用。如果采用该方法,则该方法应该返回带有数据库中未采用的数字的用户名。 例子: “贾
我正在尝试实现 Breadth-first search algorithm , 为了找到两个顶点之间的最短距离。我开发了一个 Queue 对象来保存和检索对象,并且我有一个二维数组来保存两个给定顶点
我目前正在 ika 中开发我的 Python 游戏,它使用 python 2.5 我决定为 AI 使用 A* 寻路。然而,我发现它对我的需要来说太慢了(3-4 个敌人可能会落后于游戏,但我想供应 4-
我正在寻找 Kademlia 的开源实现C/C++ 中的分布式哈希表。它必须是轻量级和跨平台的(win/linux/mac)。 它必须能够将信息发布到 DHT 并检索它。 最佳答案 OpenDHT是
我在一本书中读到这一行:-“当我们要求 C++ 实现运行程序时,它会通过调用此函数来实现。” 而且我想知道“C++ 实现”是什么意思或具体是什么。帮忙!? 最佳答案 “C++ 实现”是指编译器加上链接
我正在尝试使用分支定界的 C++ 实现这个背包问题。此网站上有一个 Java 版本:Implementing branch and bound for knapsack 我试图让我的 C++ 版本打印
在很多情况下,我需要在 C# 中访问合适的哈希算法,从重写 GetHashCode 到对数据执行快速比较/查找。 我发现 FNV 哈希是一种非常简单/好/快速的哈希算法。但是,我从未见过 C# 实现的
目录 LRU缓存替换策略 核心思想 不适用场景 算法基本实现 算法优化
1. 绪论 在前面文章中提到 空间直角坐标系相互转换 ,测绘坐标转换时,一般涉及到的情况是:两个直角坐标系的小角度转换。这个就是我们经常在测绘数据处理中,WGS-84坐标系、54北京坐标系
在软件开发过程中,有时候我们需要定时地检查数据库中的数据,并在发现新增数据时触发一个动作。为了实现这个需求,我们在 .Net 7 下进行一次简单的演示. PeriodicTimer .
二分查找 二分查找算法,说白了就是在有序的数组里面给予一个存在数组里面的值key,然后将其先和数组中间的比较,如果key大于中间值,进行下一次mid后面的比较,直到找到相等的,就可以得到它的位置。
我是一名优秀的程序员,十分优秀!