用TensorFlow写一个简单网络实现异或(XOR)

在 2017-09-20 发布于 人工智能 下以来已有715人读过本文 | 0条评论 发表评论

最近读到一个网友的博客,记录他在一次面试时,碰到面试官要求他在白板上用TensorFlow写一个简单的网络实现异或(XOR)功能。这个本身并不难,单层感知器不能解决异或问题是学习神经网络中的一个常识,而简单的两层神经网络却能将其轻易解决。但这个问题的难处在于,我们接触TensorFlow通常直接拿来写CNN,或者其他的深度学习相关的网络了,而实现这种简单网络,基本上从未做过;更何况,要求在白板上写出来,如果想bug free,并不是容易的事儿啊。

下面,我们就来简单写一下吧。其实,无论复杂还是简单,用TensorFlow写一个网络无非这样几个部分:

0.import模块

import numpy as np
import tensorflow as tf

1.输入数据的placeholder

具体来说,一个data,一个label:

data = tf.placeholder(tf.float32, shape=(4, 2))
label = tf.placeholder(tf.float32, shape=(4, 1))

由于本例比较特殊,异或只有4种输入和对应的4个输出,所以根据需求定义固定的shape。

2.基于输入数据的placeholder构建model

异或需要两层神经网络,每层分别需要一个weight和一个bias,所以定义如下:

with tf.variable_scope('layer1') as scope:
  weight = tf.get_variable(name='weight', shape=(2, 2))
  bias = tf.get_variable(name='bias', shape=(2,))
  x = tf.nn.sigmoid(tf.matmul(data, weight) + bias)
with tf.variable_scope('layer2') as scope:
  weight = tf.get_variable(name='weight', shape=(2, 1))
  bias = tf.get_variable(name='bias', shape=(1,))
  x = tf.matmul(x, weight) + bias

这里为了方便变量管理,以及在tensorboard上的条理性,使用了variable_scope,当然,也可以不使用。

此外,因为我们后面的loss要使用sigmoid_cross_entropy_with_logits函数,所以这里第二层网络的输出没有过sigmoid函数。如果loss使用其他函数,则可以做相应处理。

3.定义loss

其实这里可以灵活选用各种loss函数,比如MSE,等等。但我们还是选用了在CNN中广泛使用的cross entropy:

preds = tf.nn.sigmoid(x)
loss = tf.reduce_mean(tf.nn.sigmoid_cross_entropy_with_logits(labels=label, logits=x))

我们这里把模型的输出x过了一下sigmoid函数,作为最终输出,以便在训练时对模型进行监视。

4.定义Optimizer

learning_rate = tf.placeholder(tf.float32)
optimizer = tf.train.GradientDescentOptimizer(learning_rate).minimize(loss)

这里,我们为learning rate也定义了一个placeholder,以方便后续处理;当然也可以直接选择使用常值learning rate。

5.构建并输入数据,开始训练

train_data = np.array([[0, 0], [0, 1], [1, 0], [1, 1]])
train_label = np.array([[0], [1], [1], [0]])

with tf.Session() as sess:
  sess.run(tf.global_variables_initializer())
  for step in range(10000):
    if step < 3000:
      lr = 1
    elif step < 6000:
      lr = 0.1
    else:
      lr = 0.01
    _, l, pred = sess.run([optimizer, loss, preds], feed_dict={data: train_data, label: train_label, learning_rate: lr})
    if step % 500:
      print('Step: {} -> Loss: {} -> Predictions: {}'.format(step, l, pred)

完整代码

由此,整个网络的代码如下:

import numpy as np
import tensorflow as tf

data = tf.placeholder(tf.float32, shape=(4, 2))
label = tf.placeholder(tf.float32, shape=(4, 1))

with tf.variable_scope('layer1') as scope:
  weight = tf.get_variable(name='weight', shape=(2, 2))
  bias = tf.get_variable(name='bias', shape=(2,))
  x = tf.nn.sigmoid(tf.matmul(data, weight) + bias)
with tf.variable_scope('layer2') as scope:
  weight = tf.get_variable(name='weight', shape=(2, 1))
  bias = tf.get_variable(name='bias', shape=(1,))
  x = tf.matmul(x, weight) + bias

preds = tf.nn.sigmoid(x)
loss = tf.reduce_mean(tf.nn.sigmoid_cross_entropy_with_logits(labels=label, logits=x))
learning_rate = tf.placeholder(tf.float32)
optimizer = tf.train.GradientDescentOptimizer(learning_rate).minimize(loss)

train_data = np.array([[0, 0], [0, 1], [1, 0], [1, 1]])
train_label = np.array([[0], [1], [1], [0]])

with tf.Session() as sess:
  sess.run(tf.global_variables_initializer())
  for step in range(10000):
    if step < 3000:
      lr = 1
    elif step < 6000:
      lr = 0.1
    else:
      lr = 0.01
    _, l, pred = sess.run([optimizer, loss, preds], feed_dict={data: train_data, label: train_label, learning_rate: lr})
    if step % 500:
      print('Step: {} -> Loss: {} -> Predictions: {}'.format(step, l, pred))

也可以点击链接在GitHub上查看代码。

发表评论

您的昵称 *

您的邮箱 *

您的网站