如何改进这个cntk xor实现

时间:2017-05-24 05:56:52

标签: python neural-network cntk

我已经实施了" xor问题"用cntk(python)。

目前它只是偶尔解决问题。我怎样才能实现更可靠的网络?

我猜每当起始随机权重接近最优时,问题就会得到解决。我已经尝试binary_cross_entropy作为损失函数,但它没有改进。我尝试tanh作为非线性函数,但它也没有工作。我还尝试了许多不同的参数组合learning_rateminibatch_sizenum_minibatches_to_train。请帮忙。

由于

# -*- coding: utf-8 -*-

import numpy as np
from cntk import *
import random
import pandas as pd

input_dim = 2
output_dim = 1

def generate_random_data_sample(sample_size, feature_dim, num_classes):
    Y = []
    X = []
    for i in range(sample_size):
        if i % 4 == 0:
            Y.append([0])
            X.append([1,1])
        if i % 4 == 1:
            Y.append([0])
            X.append([0,0])
        if i % 4 == 2:
            Y.append([1])
            X.append([1,0])
        if i % 4 == 3:
            Y.append([1])
            X.append([0,1])

    return np.array(X,dtype=np.float32), np.array(Y,dtype=np.float32)   

def linear_layer(input_var, output_dim,scale=10):
    input_dim = input_var.shape[0]

    weight = parameter(shape=(input_dim, output_dim),init=uniform(scale=scale))
    bias = parameter(shape=(output_dim))

    return bias + times(input_var, weight)

def dense_layer(input_var, output_dim, nonlinearity,scale=10):
    l = linear_layer(input_var, output_dim,scale=scale)

    return nonlinearity(l)


feature = input(input_dim, np.float32)
h1 = dense_layer(feature, 2, sigmoid,scale=10)
z = dense_layer(h1, output_dim, sigmoid,scale=10)

label=input(1,np.float32)
loss = squared_error(z,label)
eval_error = squared_error(z,label)


learning_rate = 0.5
lr_schedule = learning_rate_schedule(learning_rate, UnitType.minibatch) 
learner = sgd(z.parameters, lr_schedule)
trainer = Trainer(z, (loss, eval_error), [learner])

def print_training_progress(trainer, mb, frequency, verbose=1):
    training_loss, eval_error = "NA", "NA"

    if mb % frequency == 0:
        training_loss = trainer.previous_minibatch_loss_average
        eval_error = trainer.previous_minibatch_evaluation_average
        if verbose: 
            print ("Minibatch: {0}, Loss: {1:.4f}, Error: {2:.2f}".format(mb, training_loss, eval_error))

    return mb, training_loss, eval_error

minibatch_size = 800
num_minibatches_to_train = 2000
training_progress_output_freq = 50

for i in range(0, num_minibatches_to_train):
    features, labels = generate_random_data_sample(minibatch_size, input_dim, output_dim)
    trainer.train_minibatch({feature : features, label : labels})
    batchsize, loss, error = print_training_progress(trainer, i, training_progress_output_freq, verbose=1)

out = z
result = out.eval({feature : features})
a = pd.DataFrame(data=dict(
        query=[str(int(x[0]))+str(int(x[1])) for x in features],
        test=[int(l[0]) for l in labels],
        pred=[l[0] for l in result]))
print(pd.DataFrame.drop_duplicates(a[["query","test","pred"]]).sort_values(by="test"))

4 个答案:

答案 0 :(得分:0)

我可以通过添加更多隐藏层来提高稳定性 h1 = dense_layer(feature, 5, sigmoid,scale=10)并将学习率提高到learning_rate = 0.8

这种稳定性有所改善,但它仍然经常出错。另外,将损失修改为二进制交叉熵loss = binary_cross_entropy(z,label)可以大大提高其获得正确性的机会。

在:

Minibatch: 1900, Loss: 0.1272, Error: 0.13
Minibatch: 1950, Loss: 0.1272, Error: 0.13
  query  test      pred
0    11     0  0.502307
1    00     0  0.043964
2    10     1  0.951571
3    01     1  0.498055

之后:

Minibatch: 1900, Loss: 0.0041, Error: 0.00
Minibatch: 1950, Loss: 0.0040, Error: 0.00
  query  test      pred
0    11     0  0.006617
1    00     0  0.000529
2    10     1  0.997219
3    01     1  0.994183

同样根据Davi的建议将比例从10修改为1,提高了收敛速度:

比例10:

Minibatch: 1300, Loss: 0.0732, Error: 0.01
Minibatch: 1350, Loss: 0.0483, Error: 0.00

比例1:

Minibatch: 500, Loss: 0.0875, Error: 0.01
Minibatch: 550, Loss: 0.0639, Error: 0.00

总之,需要的是:

  1. 将比例从10改为1(对于稳定的求解器,它需要更多的迭代)
  2. 从2到5添加更多隐藏图层(克服来自scale = 10但偶尔需要更多迭代的问题)
  3. 将损失函数从squared_error修改为binary_cross_entropy(收敛速度更快,即搜索正确的权重更有效)

答案 1 :(得分:0)

我不认为你可以通过直接将输入映射到输出并使用一些权重偏差来“解决”XOR 。您将需要至少一个隐藏层(至少有两个节点)。

答案 2 :(得分:0)

scale=10的四个实例更改为scale=1似乎可以解决该脚本。

我没有做任何其他更改,并且能够连续运行几次,并通过2000次迭代获得了不错的结果。当然,增加迭代次数(例如20,000或更多)会得到更好的结果。

最初的初始重量范围可能在-10到10之间,偶尔使非常大的重量使某些神经元饱和并干扰训练。贪婪的学习率可能会进一步加重这种影响。

与当前深层网络的趋势相比,XOR网络也非常稀疏。一些饱和神经元可能很难锁定深网的训练-但也许并非没有。

在过去的日子里,我似乎回想起我们经常将初始权重设置为相对较小,并且分布在零附近。不确定理论家现在建议什么。

答案 3 :(得分:0)

运行第一个发布者提供的脚本时,总是会得到与此类似的结果(只有此处给出的结果的结尾)-这是之前的结果。

...
Minibatch: 1900, Loss: 0.1266, Error: 0.13
Minibatch: 1950, Loss: 0.1266, Error: 0.13
  query  test      pred
0    11     0  0.501515
1    00     0  0.037678
2    10     1  0.497704
3    01     1  0.966931

我只重复了几次,结果却差不多。 即使将迭代次数增加到20,000,也会得到相似的结果。最初构成的此脚本似乎无法解决XOR问题。网络训练不会收敛到XOR真值表,并且误差和损失也不会收敛到零。

将4个 scale = 10 实例更改为 scale = 1 似乎总是可以解决 XOR 问题。典型结果如下。这是之后。

...
Minibatch: 1900, Loss: 0.0129, Error: 0.01
Minibatch: 1950, Loss: 0.0119, Error: 0.01
  query  test      pred
0    11     0  0.115509
1    00     0  0.084174
2    10     1  0.891398
3    01     1  0.890891

多次重新运行会产生相似的结果。训练似乎收敛于XOR真值表,而错误和损失则收敛于零。 将迭代次数增加到20,000可得到以下典型结果。现在,培训产生了可行的XOR解决方案,并且脚本似乎已“修复”。

...
Minibatch: 19900, Loss: 0.0003, Error: 0.00
Minibatch: 19950, Loss: 0.0003, Error: 0.00
  query  test      pred
0    11     0  0.017013
1    00     0  0.015626
2    10     1  0.982118
3    01     1  0.982083

更准确地说,建议的脚本更改可能会修复用于设置重量初始条件的方法。我对CNTK相当陌生,所以我不知道使用scale = 10可能会如何烘烤。由于我在CNTK程序中发现的大多数示例都是针对深层网络类型的问题,因此我怀疑使用scale = 10设置权重初始条件可能与大多数常见问题(仅在网络上发布)相关联。

最后,在这些测试过程中,系统上的库没有任何更改(安装或更新)。因此,断言库版本存在问题似乎没有事实依据。