Java:将两个双位串混合在一起以进行遗传算法交叉

标签 java genetic-algorithm evolutionary-algorithm bitarray

我正在实现进化神经网络。当涉及两个 double 值的交叉时,我遇到了问题。我正在改进神经网络中链接的权重。

    //Get the weights that I want to crossover
    double weightA = a.getWeight();
    double weightB = b.getWeight();
    //Round to 6 decimal numbers.
    weightA = (double)Math.round(weightA * 1000000) / 1000000;
    weightB = (double)Math.round(weightB * 1000000) / 1000000;
    //Convert the doubles to binary strings
    String binaryA = Long.toBinaryString(Double.doubleToRawLongBits(weightA));
    String binaryB = Long.toBinaryString(Double.doubleToRawLongBits(weightB));
    //Define random crossover point.
    int crossOverPoint = randInt(0, binaryA.length());
    //Put the strings together based on the crossover point.
    String newBinary = binaryA.substring(0,crossOverPoint) + binaryB.substring(crossOverPoint+1,binaryB.length());
    double newWeight = Double.longBitsToDouble(new BigInteger(newBinary, 2).longValue());

我遇到的问题是,交叉后我得到的权重非常大或非常小,这可能是由于每个字符串中小数位使用了多少位造成的。我应该如何做到这一点才能在交叉后获得与两个 parent 相似的值?

我有一个解决这个问题的方法,它给了我不错的结果,但我相当确定这不是正确的方法,它基本上找到两个值之间的平均值,并根据原始两个值。

    double interval = Math.abs(weightA-weightB);
    double newWeight = (weightA+weightB)*0.5 + r.nextGaussian()*interval*2;

最佳答案

我对遗传算法不太熟悉,但据我所知,您对 double 的处理似乎不是解决它的好方法:

我在这里假设您想要使用第一个 double 的二进制表示的前 crossOverPoint 位和第二个 double 的最后 (64-crossOverPoint) 位(如我错了请纠正我)。如果您使用字符串,则必须确保包含前导 0。更简单的方法是使用位运算组合长整型的二进制表示形式:

long weightALong = Double.doubleToRawLongBits(weightA);
long weightBLong = Double.doubleToRawLongBits(weightB);
long mask = -1L; // all bits set to 1
int crossOverPoint = randInt(0, Long.SIZE);
long combined;
// treat special cases because of modulo Long.SIZE of second parameter of shifting operations
if (crossOverPoint == 0) {
    combined = weightBLong;
} else if (combined == Long.SIZE) {
    combined = weightALong;
} else {
    combined = (weightALong & (mask << (Long.SIZE - crossOverPoint))) |
               (weightBLong & (mask >>> crossOverPoint));
}
double newWeight = Double.longBitsToDouble(combined);

但是从 binary representation of doubles我猜想以这种方式组合二进制表示可能不是组合 double 的最佳方式:

  • 如果第一位不同,正确选择crossOverPoint (1)就可以改变符号。
  • 在所有情况下 (52/64),指数完全来自 weightA
  • 如果尾数中出现不幸的组合,
  • NaNPOSITIVE_INFINITYNEGATIVE_INFINITY 可以由不同于这三个值的值生成.

我想你的解决方法似乎是更好的选择。 (也许你应该在 https://cs.stackexchange.com/ 上问这个问题)

关于Java:将两个双位串混合在一起以进行遗传算法交叉,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23970715/

相关文章:

c# - 产品配置器难以依存地管理数据/项目

java.lang.RuntimeException : Unable to instantiate activity ComponentInfo{…}: java. lang.ClassNotFoundException: 没有找到类

java - 我读取 XML 文档 (JDOM),在另一台 PC 上运行时出现异常 java.lang.NoClassDefFoundError

genetic-algorithm - 关于遗传算法终止条件的书籍资源

algorithm - 为什么将交叉添加到我的遗传算法中会给我带来更差的结果?

c - 进化算法达到一个恒定的适应值

selection - 理想情况下,我应该在稳态选择过程中杀死群体中的多少条染色体?

java - 尝试制作一个动态加载的java程序

java - 是否有适合 Java 1.4 和 SE (Swing) 应用程序的优秀 DI 框架?

java - 寻找进化音乐示例代码