用Python实现神经网络(五)

发布于:2025-07-24 ⋅ 阅读:(17) ⋅ 点赞:(0)

这一节告诉你如何用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训练的代价。我们不再有漂亮平滑的损失曲线。