简单的神经网络无法学习异或

2024-04-11

我正在尝试学习神经网络,并编写了一个简单的反向传播神经网络,该网络使用 sigmoid 激活函数、随机权重初始化和学习/梯度动量。

当配置 2 个输入、2 个隐藏节点和 1 个时,它无法学习 XOR 和 AND。然而,它会正确地学习 OR。

我看不到我做错了什么,所以任何帮助将不胜感激。

Thanks

EDIT:如前所述,我使用 2 个隐藏节点进行了测试,但下面的代码显示了 3 个配置。在使用 3 个隐藏节点运行测试后,我只是忘记将其更改回 2 个。

网络.rb:

module Neural

class Network

    attr_accessor :num_inputs, :num_hidden_nodes, :num_output_nodes, :input_weights, :hidden_weights, :hidden_nodes, 
                    :output_nodes, :inputs, :output_error_gradients, :hidden_error_gradients,
                    :previous_input_weight_deltas, :previous_hidden_weight_deltas

    def initialize(config)
        initialize_input(config)
        initialize_nodes(config)
        initialize_weights
    end

    def initialize_input(config)
        self.num_inputs = config[:inputs]
        self.inputs = Array.new(num_inputs+1)
        self.inputs[-1] = -1
    end

    def initialize_nodes(config)
        self.num_hidden_nodes = config[:hidden_nodes]
        self.num_output_nodes = config[:output_nodes]
        # treat threshold as an additional input/hidden node with no incoming inputs and a value of -1
        self.output_nodes = Array.new(num_output_nodes)
        self.hidden_nodes = Array.new(num_hidden_nodes+1)
        self.hidden_nodes[-1] = -1
    end

    def initialize_weights
        # treat threshold as an additional input/hidden node with no incoming inputs and a value of -1
        self.input_weights = Array.new(hidden_nodes.size){Array.new(num_inputs+1)}
        self.hidden_weights = Array.new(output_nodes.size){Array.new(num_hidden_nodes+1)}
        set_random_weights(input_weights)
        set_random_weights(hidden_weights)
        self.previous_input_weight_deltas = Array.new(hidden_nodes.size){Array.new(num_inputs+1){0}}
        self.previous_hidden_weight_deltas = Array.new(output_nodes.size){Array.new(num_hidden_nodes+1){0}}
    end

    def set_random_weights(weights)
        (0...weights.size).each do |i|
            (0...weights[i].size).each do |j|
                weights[i][j] = (rand(100) - 49).to_f / 100
            end
        end
    end

    def calculate_node_values(inputs)
        inputs.each_index do |i|
            self.inputs[i] = inputs[i]
        end

        set_node_values(self.inputs, input_weights, hidden_nodes)
        set_node_values(hidden_nodes, hidden_weights, output_nodes)
    end

    def set_node_values(values, weights, nodes)
        (0...weights.size).each do |i|
            nodes[i] = Network::sigmoid(values.zip(weights[i]).map{|v,w| v*w}.inject(:+))
        end
    end

    def predict(inputs)
        calculate_node_values(inputs)
        output_nodes.size == 1 ? output_nodes[0] : output_nodes
    end

    def train(inputs, desired_results, learning_rate, momentum_rate)
        calculate_node_values(inputs)
        backpropogate_weights(desired_results, learning_rate, momentum_rate)
    end

    def backpropogate_weights(desired_results, learning_rate, momentum_rate)
        output_error_gradients = calculate_output_error_gradients(desired_results)
        hidden_error_gradients = calculate_hidden_error_gradients(output_error_gradients)
        update_all_weights(inputs, desired_results, hidden_error_gradients, output_error_gradients, learning_rate, momentum_rate)
    end

    def self.sigmoid(x)
        1.0 / (1 + Math::E**-x)
    end

    def self.dsigmoid(x)
        sigmoid(x) * (1 - sigmoid(x))
    end

    def calculate_output_error_gradients(desired_results)
        desired_results.zip(output_nodes).map{|desired, result| (desired - result) * Network::dsigmoid(result)}
    end

    def reversed_hidden_weights
        # array[hidden node][weights to output nodes]
        reversed = Array.new(hidden_nodes.size){Array.new(output_nodes.size)}
        hidden_weights.each_index do |i|
            hidden_weights[i].each_index do |j|
                reversed[j][i] = hidden_weights[i][j];
            end
        end
        reversed

    end

    def calculate_hidden_error_gradients(output_error_gradients)
        reversed = reversed_hidden_weights
        hidden_nodes.each_with_index.map do |node, i|
            Network::dsigmoid(hidden_nodes[i]) * output_error_gradients.zip(reversed[i]).map{|error, weight| error*weight}.inject(:+)
        end
    end

    def update_all_weights(inputs, desired_results, hidden_error_gradients, output_error_gradients, learning_rate, momentum_rate)
        update_weights(hidden_nodes, inputs, input_weights, hidden_error_gradients, learning_rate, previous_input_weight_deltas, momentum_rate)
        update_weights(output_nodes, hidden_nodes, hidden_weights, output_error_gradients, learning_rate, previous_hidden_weight_deltas, momentum_rate)
    end

    def update_weights(nodes, values, weights, gradients, learning_rate, previous_deltas, momentum_rate)
        weights.each_index do |i|
            weights[i].each_index do |j|
                delta = learning_rate * gradients[i] * values[j]
                weights[i][j] += delta + momentum_rate * previous_deltas[i][j]
                previous_deltas[i][j] = delta
            end
        end


    end

end

end

test.rb:

#!/usr/bin/ruby

load "network.rb"

learning_rate = 0.3
momentum_rate = 0.2

nn = Neural::Network.new(:inputs => 2, :hidden_nodes => 3, :output_nodes => 1)
10000.times do |i|
    # XOR - doesn't work
    nn.train([0, 0], [0], learning_rate, momentum_rate)
    nn.train([1, 0], [1], learning_rate, momentum_rate)
    nn.train([0, 1], [1], learning_rate, momentum_rate)
    nn.train([1, 1], [0], learning_rate, momentum_rate)

    # AND - very rarely works
    # nn.train([0, 0], [0], learning_rate, momentum_rate)
    # nn.train([1, 0], [0], learning_rate, momentum_rate)
    # nn.train([0, 1], [0], learning_rate, momentum_rate)
    # nn.train([1, 1], [1], learning_rate, momentum_rate)

    # OR - works
    # nn.train([0, 0], [0], learning_rate, momentum_rate)
    # nn.train([1, 0], [1], learning_rate, momentum_rate)
    # nn.train([0, 1], [1], learning_rate, momentum_rate)
    # nn.train([1, 1], [1], learning_rate, momentum_rate)
end

puts "--- TESTING ---"
puts "[0, 0]"
puts "result "+nn.predict([0, 0]).to_s
puts
puts "[1, 0]"
puts "result "+nn.predict([1, 0]).to_s
puts
puts "[0, 1]"
puts "result "+nn.predict([0, 1]).to_s
puts
puts "[1, 1]"
puts "result "+nn.predict([1, 1]).to_s
puts

My answer will be not about ruby, but about neural network. First of all, you have to understand how to write your inputs and your network on a paper. If you implement binary operatos, your space will consist of four points on XY-plane. Mark true and false on X and Y axis and draw your four points. If you to it right, you will receive something like this http://drawsave.com/1Tj

Now(maybe you didn't know this interpretattion of neuron) try to draw neuron as a line on a plane, which separates your points as you need. For example, this is the line for AND: enter image description here The line separates correct answers from incorrect. If you understand, you can write the line for OR. XOR will be a trouble.

作为此调试的最后一步,将神经元实现为一条线。找到有关它的文献,我不记得如何通过现有线路构建神经元。真的,这会很简单。然后构建一个神经元向量并实现它。将 AND 实现为单个神经元网络,其中神经元被定义为在纸上计算的 AND。如果您的操作均正确,您的网络将正常运行。 我写了这么多的信只是因为你在理解任务之前编写了程序。我不想太粗鲁,但你提到的 XOR 已经表明了这一点。如果您尝试在一个神经元上构建异或,您将不会收到任何结果 - 无法区分正确答案和错误答案。在书上它被称为“XOR不是线性可分的”。因此,对于 XOR,您需要构建一个两层网络。例如,您将 AND 和非 OR 作为第一层,将 AND 作为第二层。

如果您仍然阅读本文并且理解我所写的内容,那么您在调试网络时将不会遇到任何麻烦。如果您的网络无法学习某些功能,则将其构建在纸上,然后对您的网络进行硬编码并进行测试。如果它仍然失败,那么你将其构建在错误的论文上 - 重新阅读我的讲座;)

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

简单的神经网络无法学习异或 的相关文章

随机推荐

  • 返回时如何刷新片段 UI

    我是 Android 新手 正在学习片段的知识 并为其制作了一个演示 因为我有一个片段 我们可以从中转到另一个活动 那里正在执行一些计算 然后我们当时回到片 段我想将该计算值显示到我的片段的文本视图中 那么我应该使用哪种生命周期方法来执行此
  • TypeError:无法解压不可迭代的 NoneType 对象

    我知道这个问题之前已经被问过 但我似乎无法让我的问题工作 import numpy as np def load dataset def download filename source http yaan lecun com exdb m
  • 如何从store方法获取上传的图片名称

    当我在 Laravel 中存储图像时 path request gt file myImage gt store public src 它返回完整路径 但如何仅获取给定的文件名 这是返回路径的示例 public src ltX4COwEmv
  • JPackages JavaFX + Spring boot 无法启动

    我正在尝试使用 Spring Boot 构建 JavaFX 应用程序并使用 jpackage 进行部署 当使用javafx maven plugin javafx run命令 我可以看到项目启动 但在将其构建为 msi安装程序 安装并启动
  • 使用 rvmrc 或 ruby​​-version 文件通过 RVM 设置项目 gemset?

    我使用RVM Ruby 版本管理器 https rvm io 为我的每个 Rails 项目指定 Ruby 版本和一组 gem 我有一个 rvmrc文件来自动选择 Ruby 版本和 gemset 每当我cd进入项目目录 安装 RVM 1 19
  • git-p4 正在吃掉我的图像文件

    所以 我可以使用 git p4 从 p4 导入 没有任何问题 一切似乎都正常 但我的 PNG 文件 也许还有其他文件 正在损坏 我读过有关 gitattributes 和行结束问题的内容 但我所做的一切似乎都无法改变最终结果 破碎的图像 我
  • 如何使用 joblib.dump 在 s3 上保存 sklearn 模型?

    我有一个 sklearn 模型 我想使用 joblib dump 将 pickle 文件保存在我的 s3 存储桶上 I used joblib dump model model pkl 将模型保存到本地 但我不知道如何将其保存到 s3 存储
  • C、C++ 初始化中的排序

    考虑以下初始化 C C int a f g struct int x y foo f g C struct goo goo int x int y goo b f g goo c f g C 11 goo d f g 是执行顺序f and
  • 将内核内置模块替换为可加载模块

    我开发了一个内核模块来管理 nf4 标签作为字符设备 我在内核之外开发了这个模块 并在开发阶段将其编译为可加载内核模块 即 ko 进行了测试 一旦驱动程序功能正常且足够稳定 我就使用补丁将其插入 Linux 内核源代码 v4 9 30 以便
  • 可执行的 Spring Boot 2 jar

    我尝试安装我的 Spring Boot 应用程序 第一步 我尝试创建一个可执行 jar 如下所述 https docs spring io spring boot docs current reference html deployment
  • Django CreateView过滤选择字段中的外键

    我需要一些有关 Django 2 和 Python 3 的帮助 我正在使用一个CreateView在我的数据库中添加新记录 但我需要为我的记录创建一个过滤器Aviso表单页面使选择字段 fieldturma 仅显示其中的实例represen
  • 在 C# 中以科学记数法显示 IEEE-754 四倍精度 (binary128) 浮点值

    我正在尝试将原始二进制数据从线程上下文转换为人类可读的格式 并且在尝试转换时出现空的情况四精度浮点 http en wikipedia org wiki Quadruple precision floating point format I
  • 访问Scheme中的调用堆栈深度

    为了演示尾递归的有效性 我想要一种在Scheme中动态访问调用堆栈深度的方法 有没有办法做到这一点 如果没有 有没有办法在其他主要函数语言 OCaml Haskell 等 中做到这一点 Racket 允许您在调用堆栈中存储值 您可以使用它来
  • 如何删除indexedDB?

    我正在从事一个涉及使用 IndexedDB 的项目 当我开始了解这项技术时 我需要能够手动删除索引数据库 以便我可以重新开始 我在 Firefox 中找到了方法 但在 Google Chrome 中找不到方法 我尝试删除该文件夹的内容 我使
  • 在运行时访问 build-id

    我试图弄清楚如何访问链接器在运行时生成的构建 ID 从这个页面开始 https linux die net man 1 ld https linux die net man 1 ld 当我构建一个测试程序时 例如 gcc test c o
  • Spring Batch 跳过 ItemWriter 异常

    我正在尝试将 Spring Batch 2 2 5 与 Java 配置一起使用 这是我的配置 Configuration EnableBatchProcessing public class JobConfiguration Autowir
  • 我需要做什么才能让 ZMQ_RADIO / ZMQ_DISH 正常工作?

    我正在尝试使用 ZMQ 草案规范ZMQ RADIO and ZMQ DISH 我用 CMake 构建了 libzmq 和 cppzmqExternalProject和旗帜ENABLE DRAFTS ON并验证它是使用草稿建造的zmq has
  • 如何使用 dapper 将 DbGeography 插入 SQL Server

    我已经创建了模型using System Data Entity Spatial public class Store public int Id get private set public string Name get set pub
  • 将自签名 https 证书添加到 teamcity 后,TeamCity 构建代理会断开连接

    我向 Teamcity BuildServer 添加了一个自签名证书以引入 https 支持 以便现在可以通过以下地址访问它 https ServerUrl 8443 有关如何进行的更多详细信息here http tomcat apache
  • 简单的神经网络无法学习异或

    我正在尝试学习神经网络 并编写了一个简单的反向传播神经网络 该网络使用 sigmoid 激活函数 随机权重初始化和学习 梯度动量 当配置 2 个输入 2 个隐藏节点和 1 个时 它无法学习 XOR 和 AND 然而 它会正确地学习 OR 我