神经网络近似FizzBuzz

近似FizzBuzz

我正在尝试近似著名的FizzBuzz函数:

def fizzbuzz(start, end):    a = list()    for i in range(start, end + 1):        a.append(fb(i))    return adef fb(i):    if i % 3 == 0 and i % 5 == 0:        return "FizzBuzz"    elif i % 3 == 0:        return "Fizz"    elif i % 5 == 0:        return "Buzz"    else:        return i

问题是,训练后,对于1到100之间的所有值,我只得到了数字作为输出:

[  1   2   3   4   5   6   7   8   9  10  11  12  13  14  15  16  17  18  19  20  21  22  23  24  25  26  27  28  29  30  31  32  33  34  35  36  37  38  39  40  41  42  43  44  45  46  47  48  49  50  51  52  53  54  55  56  57  58  59  60  61  62  63  64  65  66  67  68  69  70  71  72  73  74  75  76  77  78  79  80  81  82  83  84  85  86  87  88  89  90  91  92  93  94  95  96  97  98  99 100]

正确的输出应该是:

['1' '2' 'Fizz' '4' 'Buzz' 'Fizz' '7' '8' 'Fizz' 'Buzz' '11' 'Fizz' '13' '14' 'FizzBuzz' '16' '17' 'Fizz' '19' 'Buzz' 'Fizz' '22' '23' 'Fizz' 'Buzz' '26' 'Fizz' '28' '29' 'FizzBuzz' '31' '32' 'Fizz' '34' 'Buzz' 'Fizz' '37' '38' 'Fizz' 'Buzz' '41' 'Fizz' '43' '44' 'FizzBuzz' '46' '47' 'Fizz' '49' 'Buzz' 'Fizz' '52' '53' 'Fizz' 'Buzz' '56' 'Fizz' '58' '59' 'FizzBuzz' '61' '62' 'Fizz' '64' 'Buzz' 'Fizz' '67' '68' 'Fizz' 'Buzz' '71' 'Fizz' '73' '74' 'FizzBuzz' '76' '77' 'Fizz' '79' 'Buzz' 'Fizz' '82' '83' 'Fizz' 'Buzz' '86' 'Fizz' '88' '89' 'FizzBuzz' '91' '92' 'Fizz' '94' 'Buzz' 'Fizz' '97' '98' 'Fizz' 'Buzz']

我的神经网络将每个数字分类为四类之一:

0. "Fizz"1. "Buzz"2. "FizzBuzz"3. 以上皆非

我认为我的神经网络正在学习将每个数字分类到最常被标记为正确类的类别(即第3类:以上皆非),但我不知道如何解决这个问题。

准备数据

我将X(输入)值编码为16位二进制:

def binary_encode_16b_array(a):    encoded_a = list()    for elem in a:        encoded_a.append(binary_encode_16b(elem))    return np.array(encoded_a)def binary_encode_16b(val):    bin_arr = list()    bin_str = format(val, '016b')    for bit in bin_str:        bin_arr.append(bit)    return np.array(bin_arr)

并将Y(输出)值编码为one-hot向量:

def one_hot_encode_array(a):    encoded_a = list()    for elem in a:        encoded_a.append(one_hot_encode(elem))    return np.array(encoded_a)def one_hot_encode(val):    if val == 'Fizz':        return np.array([1, 0, 0, 0])    elif val == 'Buzz':        return np.array([0, 1, 0, 0])    elif val == 'FizzBuzz':        return np.array([0, 0, 1, 0])    else:        return np.array([0, 0, 0, 1])

这将把16位二进制输入数据分类为FizzBuzz规则指定的4个可能类别之一。

例如,如果返回[ 0.03 -0.4 -0.4 0.4],程序知道不打印任何”Fizz”、”Buzz”或”FizzBuzz”:

# 解码Y的值def one_hot_decode_array(x, y):    decoded_a = list()    for index, elem in enumerate(y):        decoded_a.append(one_hot_decode(x[index], elem))    return np.array(decoded_a)def one_hot_decode(x, val):    index = np.argmax(val)    if index == 0:        return 'Fizz'    elif index == 1:        return 'Buzz'    elif index == 2:        return 'FizzBuzz'    elif index == 3:        return x

初始化数据

这是我如何划分训练和测试数据:

# 使用不会被测试的数据进行训练test_x_start = 1test_x_end = 100train_x_start = 101train_x_end = 10000test_x_raw = np.arange(test_x_start, test_x_end + 1)test_x = binary_encode_16b_array(test_x_raw).reshape([-1, 16])test_y_raw = fizzbuzz(test_x_start, test_x_end)test_y = one_hot_encode_array(test_y_raw)train_x_raw = np.arange(train_x_start, train_x_end + 1)train_x = binary_encode_16b_array(train_x_raw).reshape([-1, 16])train_y_raw = fizzbuzz(train_x_start, train_x_end)train_y = one_hot_encode_array(train_y_raw)

因此,模型使用101到10000之间的值进行训练,并使用1到100之间的值进行测试。

神经网络模型

我的模型架构很简单,包含一个隐藏层,拥有100个隐藏神经元:

# 定义参数input_dim = 16output_dim = 4h1_dim = 100# 构建图X = tf.placeholder(tf.float32, [None, input_dim])Y = tf.placeholder(tf.float32, [None, output_dim])h1_w = tf.Variable(tf.zeros([input_dim, h1_dim]))h1_b = tf.Variable(tf.zeros([h1_dim]))h1_z = tf.nn.relu(tf.matmul(X, h1_w) + h1_b)fc_w = tf.Variable(tf.zeros([h1_dim, output_dim]))fc_b = tf.Variable(tf.zeros([output_dim]))Z = tf.matmul(h1_z, fc_w) + fc_b# 定义损失cross_entropy = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(labels=Y, logits=Z))# 定义优化器train_step = tf.train.AdamOptimizer(0.005).minimize(cross_entropy)# 定义准确率correct_prediction = tf.equal(tf.argmax(Z, 1), tf.argmax(Y, 1))correct_prediction = tf.cast(correct_prediction, tf.float32)accuracy = tf.reduce_mean(correct_prediction)

运行模型

为了简单起见,我选择了不使用批量训练:

with tf.Session() as sess:    sess.run(tf.global_variables_initializer())    for i in range(1000):        sess.run(train_step, feed_dict={X: train_x, Y: train_y})        train_accuracy = sess.run(accuracy, feed_dict={X: train_x, Y: train_y})        print(i, ":", train_accuracy)    output = sess.run(Z, feed_dict={X: test_x})    decoded = one_hot_decode_array(test_x_raw, output)    print(decoded)

在训练过程中,准确率值未能超过0.533333。网络被训练为仅根据规则!(i%3==0 || i%5==0) ? i输出数字,这是FizzBuzz函数中最常见的答案。

编辑:已解决

使用下面@[隐藏人名]提供的解决方案,我将隐藏层和输出层的初始值设为均匀随机。增加迭代次数并降低AdamOptimizer的学习率,我的模型现在在测试数据集上表现完美。我已将工作模型的源代码上传到GitHub仓库中。


回答:

在你的网络中,将所有初始权重设置为相同的值(零)会抵消层内多个神经元的任何好处。随机初始化权重是必要的:

h1_w = tf.Variable(tf.random_normal([input_dim, h1_dim], stddev=0.1))

我的准确率在约200次迭代后才开始变化,但在1000次迭代后,测试集上的准确率达到了0.99。我有点惊讶这甚至只用一个隐藏层就能工作。

Related Posts

使用LSTM在Python中预测未来值

这段代码可以预测指定股票的当前日期之前的值,但不能预测…

如何在gensim的word2vec模型中查找双词组的相似性

我有一个word2vec模型,假设我使用的是googl…

dask_xgboost.predict 可以工作但无法显示 – 数据必须是一维的

我试图使用 XGBoost 创建模型。 看起来我成功地…

ML Tuning – Cross Validation in Spark

我在https://spark.apache.org/…

如何在React JS中使用fetch从REST API获取预测

我正在开发一个应用程序,其中Flask REST AP…

如何分析ML.NET中多类分类预测得分数组?

我在ML.NET中创建了一个多类分类项目。该项目可以对…

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注