这一节告诉你如何用TensorFlow实现全连接网络。
安装 DeepChem
这一节,你将使用DeepChem 机器学习工具链进行实验在网上可以找到 DeepChem详细安装指导。
Tox21 Dataset
作为我们的建模案例研究,我们使用化学数据库。毒理学家很感兴趣于用机器学习来预测化学物是有毒。这个任务很复杂,因为令天的科学对代谢过程了解得很少。但是,生物学家和化学家用有限的实验来提示毒性。如果一个化学物命中这个实验之一,它很可能对人类有毒。但是这些实验成本很高。所以数据学家构建机器学习模型来预测新化合物的结果。
一个重要的毒理学数据集是Tox21。我们分析 Tox21里的其中一个数据集。这个数据集有 10,000个化学物与雄激素受体的相互作有用。数据科学家需要预测新化合物是否与雄激素受体有相互作用。处理数据集很有技巧,所有要用DeepChem里的MoleculeNet 数据集。 Each molecule in Tox21里的分子被DeepChem处理为长度为1024的位-向量。简单的调用DeepChem来加载数据集 (Example 4-1).
Example 4-1. Load the Tox21 dataset
import deepchem as dc
_, (train, valid, test), _ = dc.molnet.load_tox21()
train_X, train_y, train_w = train.X, train.y, train.w
valid_X, valid_y, valid_w = valid.X, valid.y, valid.w
test_X, test_y, test_w = test.X, test.y, test.w
这里 X是处理过的特征向量, y 是标签, w 是权重。标签是 1/0 表示是否与雄激素交互。 Tox21 存贮不平衡数据集,正样本数少于负样本数。所有的变量为NumPy 数组。Tox21有很多数据集我们不需要在这里分析,所以我们要去除这相关的数据集的标签。 (Example 4-2).
Example 4-2. Remove extra datasets from Tox21
# Remove extra tasks
train_y = train_y[:, 0]
valid_y = valid_y[:, 0]
test_y = test_y[:, 0]
train_w = train_w[:, 0]
valid_w = valid_w[:, 0]
test_w = test_w[:, 0]
接收Minibatches为Placeholders
(Example 4-3).
Example 4-3. Defining placeholders that accept minibatches of different sizes
d = 1024
with tf.name_scope("placeholders"):
x = tf.placeholder(tf.float32, (None, d))
y = tf.placeholder(tf.float32, (None,))
Note d is 1024, the dimensionality of our feature vectors.
实现隐藏层
Example 4-4.
Example 4-4. Defining a hidden layer
with tf.name_scope("hidden-layer"):
W = tf.Variable(tf.random_normal((d, n_hidden)))
b = tf.Variable(tf.random_normal((n_hidden,)))
x_hidden = tf.nn.relu(tf.matmul(x, W) + b)
我们使用 tf.nn.relu激活函数。其它代码与逻辑回归的代码相似。
Example 4-5.
Example 4-5. Defining the fully connected architecture
with tf.name_scope("placeholders"):
x = tf.placeholder(tf.float32, (None, d))
y = tf.placeholder(tf.float32, (None,))
with tf.name_scope("hidden-layer"):
W = tf.Variable(tf.random_normal((d, n_hidden)))
b = tf.Variable(tf.random_normal((n_hidden,)))
x_hidden = tf.nn.relu(tf.matmul(x, W) + b)
with tf.name_scope("output"):
W = tf.Variable(tf.random_normal((n_hidden, 1)))
b = tf.Variable(tf.random_normal((1,)))
y_logit = tf.matmul(x_hidden, W) + b
# the sigmoid gives the class probability of 1
y_one_prob = tf.sigmoid(y_logit)
# Rounding P(y=1) will give the correct prediction.
y_pred = tf.round(y_one_prob)
with tf.name_scope("loss"):
# Compute the cross-entropy term for each datapoint
y_expand = tf.expand_dims(y, 1)
entropy = tf.nn.sigmoid_cross_entropy_with_logits(logits=y_logit, labels=y_expand)
# Sum all contributions
l = tf.reduce_sum(entropy)
with tf.name_scope("optim"):
train_op = tf.train.AdamOptimizer(learning_rate).minimize(l)
with tf.name_scope("summaries"):
tf.summary.scalar("loss", l)
merged = tf.summary.merge_all()
添加Dropout到隐藏层
TensorFlow 使用tf.nn.dropout(x, keep_prob)为我们实现dropout,其中 keep_prob 是节点保留的概率。记住在训练时打开dropout,预测时关闭dropout。 Example 4-6.
Example 4-6. Add a placeholder for dropout probability
keep_prob = tf.placeholder(tf.float32)
在训练时我们传递希望的值,通常 0.5,测试时我们设置keep_prob 为1.0 因为我们要用学习过的节点进行预测。添加dropout到全连接网络只需要额外的一行代码。(Example 4-7).
Example 4-7. Defining a hidden layer with dropout
with tf.name_scope("hidden-layer"):
W = tf.Variable(tf.random_normal((d, n_hidden)))
b = tf.Variable(tf.random_normal((n_hidden,)))
x_hidden = tf.nn.relu(tf.matmul(x, W) + b)
# Apply dropout
x_hidden = tf.nn.dropout(x_hidden, keep_prob)
实施Minibatching
我们用NumPy数组切片实现 (Example 4-8).
Example 4-8. Training on minibatches
step = 0
for epoch in range(n_epochs):
pos = 0
while pos < N:
batch_X = train_X[pos:pos+batch_size]
batch_y = train_y[pos:pos+batch_size]
feed_dict = {x: batch_X, y: batch_y, keep_prob: dropout_prob}
_, summary, loss = sess.run([train_op, merged, l], feed_dict=feed_dict)
print("epoch %d, step %d, loss: %f" % (epoch, step, loss))
train_writer.add_summary(summary, step)
step += 1
pos += batch_size
评估模型的准确性Evaluating Model Accuracy
我们要用验证集来测量准确性。但是不平衡数据需要点技巧。我们的数据集里有 95% 有数据标签为0 只有 5% 的标签为1。结果所有的0 模型将有95%准确率!这不是我们想要的。更好的选择是增加正样本的权重。计算加权的准确性,我们使用 accuracy_score(true,
pred, sample_weight=given_sample_weight) 来自sklearn.metrics。这个函数的关键参数是sample_weight,让我们指明希望的权重(Example 4-9).
Example 4-9. Computing a weighted accuracy
train_weighted_score = accuracy_score(train_y, train_y_pred, sample_weight=train_w)
print("Train Weighted Classification Accuracy: %f" % train_weighted_score)
valid_weighted_score = accuracy_score(valid_y, valid_y_pred, sample_weight=valid_w)
print("Valid Weighted Classification Accuracy: %f" % valid_weighted_score)
现在我们训练模型 (黙认 10)并测量准确性:
Train Weighted Classification Accuracy: 0.742045
Valid Weighted Classification Accuracy: 0.648828
使用TensorBoard跟踪模型的收敛
我们用TensorBoard来观察模型。首先检图结构 (Figure 4-35).
然后扩展隐藏层(Figure 4-36).
图 4-35. 可视化全连接网络的计算图.
图 4-36. 可视化全连接网络的扩展计算图.
你可以看到可训练参数和dropout操作在这里是如何呈现的。下面是损失曲线 (Figure 4-37).
图4-37. 可视化全连接网络的损失曲线.
我们放大看仔细点 (Figure 4-38).
图 4-38. 局部放大损失曲线
看起来并不平! 这就是使用 minibatch训练的代价。我们不再有漂亮平滑的损失曲线。