首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >问答首页 >一种神经网络求解异或进化算法的改进

一种神经网络求解异或进化算法的改进
EN

Stack Overflow用户
提问于 2014-12-09 13:17:25
回答 1查看 496关注 0票数 3

我应该实现一个具有2个输入、2个隐藏和1个输出神经元的人工神经网络(ANN),它可以解决XOR问题。应该使用进化算法来优化网络的权重。给出了每个神经元的激活函数和每个神经网络的适应度函数。下图总结了这个问题,并介绍了我使用的变量名:

现在我尽了最大的努力来解决这个问题,但即使使用1000个ANN和2000代的进化算法,我的最佳适应度也永远不会超过0.75。我的代码包括一个带有神经元、激活和适应度函数的ANN类,以及一个包含进化算法并优化ANN权重的主类。代码如下:

每个ANN用-1和1之间的随机权重进行初始化,并且能够变异,即返回一个随机选择的权重不同的变异。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public class ANN implements Comparable<ANN> {
    private Random rand = new Random();
    public double[] w = new double[6];  //weights: in1->h1, in1->h2, in2->h1, in2->h2, h1->out, h2->out

    public ANN() {
        for (int i=0; i<6; i++) //randomly initialize weights in [-1,1)
            w[i] = rand.nextDouble() * 2 - 1;
    }

    //calculates the output for input a & b
    public double ann(double a, double b) {
        double h1 = activationFunc(a*w[0] + b*w[2]);
        double h2 = activationFunc(a*w[1] + b*w[3]);
        double out = activationFunc(h1*w[4] + h2*w[5]);

        return out;
    }

    private double activationFunc(double x) {
        return 2.0 / (1 + Math.exp(-2*x)) - 1;
    }

    //calculates the fitness (divergence to the right output)
    public double fitness() {
        double sum = 0;
        //test all possible inputs (0,0; 0,1; 1,0; 1,1)
        sum += 1 - Math.abs(0 - ann(0, 0));
        sum += 1 - Math.abs(1 - ann(0, 1));
        sum += 1 - Math.abs(1 - ann(1, 0));
        sum += 1 - Math.abs(0 - ann(1, 1));
        return sum / 4.0;
    }

    //randomly change random weight and return the mutated ANN
    public ANN mutate() {
        //copy weights
        ANN mutation = new ANN();
        for (int i=0; i<6; i++)
            mutation.w[i] = w[i];

        //randomly change one
        int weight = rand.nextInt(6);
        mutation.w[weight] = rand.nextDouble() * 2 - 1;

        return mutation;
    }

    @Override
    public int compareTo(ANN arg) {
        if (this.fitness() < arg.fitness())
            return -1;
        if (this.fitness() == arg.fitness())
            return 0;
        return 1;   //this.fitness > arg.fitness
    }

    @Override
    public boolean equals(Object obj) {
        if (obj == null)
            return false;
        ANN ann = (ANN)obj;
        for (int i=0; i<w.length; i++) {    //not equal if any weight is different
            if (w[i] != ann.w[i])
                return false;
        }
        return true;
    }
}

主类具有进化算法,并使用精英主义和基于排名的选择来创建每个种群的下一代,即复制100个最好的人工神经网络,其余900个是先前成功的人工神经网络的突变。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
//rank-based selection + elitism
public class Main {
    static Random rand = new Random();
    static int size = 1000;                     //population size
    static int elitists = 100;                  //number of elitists

    public static void main(String[] args) {
        int generation = 0;
        ArrayList<ANN> population = initPopulation();
        print(population, generation);

        //stop after good fitness is reached or after 2000 generations
        while(bestFitness(population) < 0.8 && generation < 2000) {
            generation++;
            population = nextGeneration(population);
            print(population, generation);
        }
    }

    public static ArrayList<ANN> initPopulation() {
        ArrayList<ANN> population = new ArrayList<ANN>();
        for (int i=0; i<size; i++) {
            ANN ann = new ANN();
            if (!population.contains(ann))  //no duplicates
                population.add(ann);
        }
        return population;
    }

    public static ArrayList<ANN> nextGeneration(ArrayList<ANN> current) {
        ArrayList<ANN> next = new ArrayList<ANN>();
        Collections.sort(current, Collections.reverseOrder());  //sort according to fitness (0=best, 999=worst)

        //copy elitists
        for (int i=0; i<elitists; i++) {
            next.add(current.get(i));
        }

        //rank-based roulette wheel
        while (next.size() < size) {                        //keep same population size
            double total = 0;
            for (int i=0; i<size; i++)
                total += 1.0 / (i + 1.0);                   //fitness = 1/(rank+1)

            double r = rand.nextDouble() * total;
            double cap = 0;
            for (int i=0; i<size; i++) {
                cap += 1.0 / (i + 1.0);                     //higher rank => higher probability
                if (r < cap) {                              //select for mutation
                    ANN mutation = current.get(i).mutate(); //no duplicates
                    if (!next.contains(mutation))
                        next.add(mutation);     
                    break;
                }
            }
        }       

        return next;
    }

    //returns best ANN in the specified population
    public static ANN best(ArrayList<ANN> population) {
        Collections.sort(population, Collections.reverseOrder());
        return population.get(0);
    }

    //returns the best fitness of the specified population
    public static double bestFitness(ArrayList<ANN> population) {
        return best(population).fitness();
    }

    //returns the average fitness of the specified population
    public static double averageFitness(ArrayList<ANN> population) {
        double totalFitness = 0;
        for (int i=0; i<size; i++)
            totalFitness += population.get(i).fitness();
        double average = totalFitness / size;
        return average;
    }

    //print population best and average fitness
    public static void print(ArrayList<ANN> population, int generation) {       
        System.out.println("Generation: " + generation + "\nBest: " + bestFitness(population) + ", average: " + averageFitness(population));
        System.out.print("Best weights: ");
        ANN best = best(population);
        for (int i=0; i<best.w.length; i++)
            System.out.print(best.w[i] + " ");
        System.out.println();
        System.out.println();
    }
}

尽管我在这方面花了相当多的心思,并使用了我学到的技术,但结果并不令人满意。由于某些原因,对于每个权重,最优权重似乎会漂移到-1。这怎么说得通呢?权重的范围从-1到1是否是一个好的选择?除了突变之外,我还应该引入交叉吗?我知道这是一个非常具体的问题,但我会非常感谢一些帮助!

EN

回答 1

Stack Overflow用户

发布于 2015-06-04 16:19:02

网络结构不正确。如果没有每个节点的偏差或阈值,这个网络就不能解决XOR问题。

一个隐藏节点应该对OR进行编码,另一个隐藏节点应该对AND进行编码。然后,对于XOR问题,输出节点可以编码OR隐藏节点为正,而and隐藏节点为负。只有当OR隐藏节点被激活而and隐藏节点未被激活时,这才会产生积极的结果。

我还会增加权重的边界,让EA自己找出来。但这取决于网络结构,如果有必要的话。

如果要将此网络与隐藏节点和阈值一起使用,请参阅:http://www.heatonresearch.com/online/introduction-neural-networks-java-edition-2/chapter-1/page4.html

如果您想使用另一个带有偏差的网络,请参阅:http://www.mind.ilstu.edu/curriculum/artificial_neural_net/xor_problem_and_solution.php

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/27379864

复制
相关文章
Makefile文件
title: Makefile文件 文章目录 title: Makefile文件 Makefile文件 Makefile文件 make命令执行时,需要一个makefile文件,以告诉make命令需要怎么样的去编译和链接程序。 image.png image.png image.png image.png
AI拉呱
2021/01/14
6080
输出cglib以及jdk动态代理产生的class文件
好奇心重的小伙伴有一种知其然,亦欲知其所以然的特性,我们在spring事务应用中会接触到aop技术,而aop背后隐藏的恰恰是以jdk以及cglib为基础的动态代理技术,博主不才,将自己的学习历程记录于此,希望帮到有需求的同行,其实我们仅需要进行简单的设置,即可输出cglib以及jdk动态代理产生的class文件,然后使用jdt或者其他工具查看生成的动态代理类,以验证理论知识:
johnhuster的分享
2022/03/29
5420
Makefile文件编写
make 的参数有很多, 可以通过 make -h 去查看, 下面只介绍几个我认为比较有用的。
用户2929716
2018/08/23
1.2K0
Makefile 文件格式;makefile伪目标
           第二行的gcc -o test prog.o code.o是可运行命令。
西湖醋鱼
2020/12/30
8290
多文件目录Makefile的写法
  linux下程序开发,涉及到多个文件,多个目录,这时候编译文件的任务量比较大,需要写Makefile
杨永贞
2020/08/04
4K0
多文件目录Makefile的写法
EditPlus如何设置保存时不产生.bak备份文件?
大家在使用EditPlus时都会遇到这么一个问题,就是每次保存或者修改后保存时都会生成一个.bak后缀的文件,这个是一个缓存文件。那如何才能不生成该缓存文件呢?操作如下图所示:
黑泽君
2018/10/11
1.5K0
makefile 指定文件的生成目录[通俗易懂]
1.上一篇博客虽然简单实现了自动处理依赖关系,但是生成的各种临时文件都混在一起,太乱了。
全栈程序员站长
2022/09/01
4.3K0
makefile文件编写「建议收藏」
makefile文件用于管理和组织代码工程的编译和链接,其不是可执行文件,其被make工具解析并完成相关动作,下面笔者将介绍makefile中常用的一些语法说明:
全栈程序员站长
2022/09/06
3.3K0
makefile文件编写「建议收藏」
【Makefile】简单的Makefile编写
Makefile编写 程序的编译和链接 使用C、C++编写可执行文件,首先要把源文件编译成中间代码文件,Linux下是.o文件,即Object File,这个动作叫做编译(complie)。 然后再把大量的Object File合成执行文件,这个动作叫链接(link)。 一个项目会拥有成百上千个源程序文件,再使用G++ or GCC会很麻烦。于是Makefile闪亮登场。 Makefile确定整个工程的编译规则,只需要一个make命令,就可以实现“自动化编译”。 make是一个解释Make
半生瓜的blog
2023/05/13
1K0
【Makefile】简单的Makefile编写
make命令和makefile文件
  make命令和makefile文件的结合提供了一个在项目管理领域十分强大的工具,它不仅常被用于控制源代码的编译,而且还用于手册页的编写以及将应用程序安装到目标目录。
全栈程序员站长
2022/07/18
2.6K0
浅谈内核的Makefile、Kconfig和.config文件
Linux内核源码文件繁多,搞不清Makefile、Kconfig、.config间的关系,不了解内核编译体系,编译修改内核有问题无从下手,自己写的驱动不知道怎么编进内核,不知道怎么配置内核,这些问题都和Makefile、Kconfig、.config有关,下面简单谈谈Makefile、Kconfig和.config。希望对你有启发。
韦东山
2020/09/30
3.8K0
浅谈内核的Makefile、Kconfig和.config文件
Scrapy之日志文件的产生
我们写爬虫的时候,也许会需要记录一些数据或者异常信息,通常这些数据我们会希望以日志的形式保存下来。
钱塘小甲子
2019/01/29
9120
一个Makefile 文件实例模板
1  在Linux下,一般使用GCC文件,比较头疼的问题,每次编写Makefile文件,比较麻烦,关键是经常忘记makefile语法;
无限之生
2020/06/30
7240
5个编写高效Makefile文件的最佳实践
在编写Makefile文件之前,我们需要明确我们的目标是什么。我们需要知道我们需要构建哪些文件,以及它们之间的依赖关系。为了确定目标,我们需要考虑以下问题:
小万哥
2023/05/20
3040
5个编写高效Makefile文件的最佳实践
设置打印输出不缓冲
❝通过设置setvbuf函数达到打印输出不缓冲的功能,以消除输出延时。❞ 原型 int setvbuf(FILE *stream, char *buffer, int mode, size_t size); 「stream」:将缓冲区设置为文件流。 「buffer」:指向流使用的缓冲区的指针,或指向仅更改大小和模式的空指针。 「mode」:缓冲模式使用。它有以下值之一: _IOFBF 全缓冲 _IOLBF 行缓冲 _IONBF 没有缓冲 「size」:缓冲区大小。 返回为0即成功,否则失败。 使用   
Qt君
2020/04/17
2.2K0
为sourceinsight添加makefile和configure文件
在用sourceinsight查看ffmpeg源码的时候,大家会发现不能查看源码中的makefile代码,即不能搜索到makefile文件。这是因为source insight默认是不选makefile的,也没有configure这种类型的文件。下面就说如何让sourceinsight支持查看makefile和configure代码:
雪影
2018/08/02
1.1K0
年薪百万的机器学习专家,为什么不产生价值?
本文转载自第四范式知乎专栏,量子位已获得授权。 「范式大学系列课程」第 3 篇文章: 年薪百万的机器学习专家,为什么不产生价值? Part 1 一个朋友的企业,他们招聘了 2 名机器学习方向的数据科学
量子位
2018/03/30
6470
年薪百万的机器学习专家,为什么不产生价值?
点击加载更多

相似问题

简单的makefile不产生输出文件(正确)

11

解析不产生预期输出

13

函数不产生预期输出

13

DFS方法不产生预期输出

10

Java - cast不产生预期的输出

12
添加站长 进交流群

领取专属 10元无门槛券

AI混元助手 在线答疑

扫码加入开发者社群
关注 腾讯云开发者公众号

洞察 腾讯核心技术

剖析业界实践案例

扫码关注腾讯云开发者公众号
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
查看详情【社区公告】 技术创作特训营有奖征文