表格数据:在不求助于迭代的情况下实现自定义张量层
Tabular data: Implementing a custom tensor layer without resorting to iteration
我有一个通过迭代不难实现的张量操作的想法,批量大小为 1。但是我想尽可能地并行化它。
我有两个形状为 (n, 5) 的张量,称为 X 和 Y。X 实际上应该表示形状为 (n, 1) 的 5 个一维张量:(x_1, ... , x_n). Y 同上
我想计算一个形状为 (n, 25) 的张量,其中每一列代表张量运算 f(x_i, y_j) 的输出,其中 f 对所有对象都是固定的1 <= i, j <= 5。操作 f 的输出形状为 (n, 1),就像 x_i 和 y_i.
我觉得有必要澄清一下,f 本质上是一个来自串联 [...x_i, ...y_i] 张量的全连接层,形状为 (1, 10 ), 到形状为 (1,5) 的输出层。
同样,很容易看出如何通过迭代和切片手动执行此操作。但是,这可能非常慢。分批执行此操作,其中张量 X、Y 现在具有形状 (n, 5, batch_size) 也是可取的,特别是对于小批量梯度下降。
这里很难说清楚为什么我想创建这个网络;我觉得它适合我的 'itemized tabular data' 领域,并且与完全连接的网络相比,每次操作的权重数量显着减少。
这可以使用 tensorflow 吗?当然不只是使用keras。
以下是根据 AloneTogether 的请求
在 numpy 中的示例
import numpy as np
features = 16
batch_size = 256
X_batch = np.random.random((features, 5, batch_size))
Y_batch = np.random.random((features, 5, batch_size))
# one tensor operation to reduce weights in this custom 'layer'
f = np.random.random((features, 2 * features))
for b in range(batch_size):
X = X_batch[:, :, b]
Y = Y_batch[:, :, b]
for i in range(5):
x_i = X[:, i:i+1]
for j in range(5):
y_j = Y[:, j:j+1]
x_i_y_j = np.concatenate([x_i, y_j], axis=0)
# f(x_i, y_j)
# implemented by a fully-connected layer
f_i_j = np.matmul(f, x_i_y_j)
您需要的所有操作(串联和矩阵乘法)都可以进行批处理。
这里的困难部分是,您想要将 X 中所有项目的特征与 Y 中所有项目的特征(所有组合)连接起来。
我推荐的解决方案是将 X 的维度扩展到 [batch, features, 5, 1]
,将 Y 的维度扩展到 [batch, features, 1, 5]
比 tf.repeat()
两个张量所以它们的形状变成 [batch, features, 5, 5]
。
现在您可以连接 X 和 Y。您将得到一个形状为 [batch, 2*features, 5, 5]
的张量。观察以这种方式构建所有组合。
下一步是矩阵乘法。 tf.matmul()
也可以做批量矩阵乘法,但我在这里使用 tf.einsum()
因为我想更多地控制哪些维度被视为批量。
完整代码:
import tensorflow as tf
import numpy as np
batch_size=3
features=6
items=5
x = np.random.uniform(size=[batch_size,features,items])
y = np.random.uniform(size=[batch_size,features,items])
f = np.random.uniform(size=[2*features,features])
x_reps= tf.repeat(x[:,:,:,tf.newaxis], items, axis=3)
y_reps= tf.repeat(y[:,:,tf.newaxis,:], items, axis=2)
xy_conc = tf.concat([x_reps,y_reps], axis=1)
f_i_j = tf.einsum("bfij, fg->bgij", xy_conc,f)
f_i_j = tf.reshape(f_i_j , [batch_size,features,items*items])
我有一个通过迭代不难实现的张量操作的想法,批量大小为 1。但是我想尽可能地并行化它。
我有两个形状为 (n, 5) 的张量,称为 X 和 Y。X 实际上应该表示形状为 (n, 1) 的 5 个一维张量:(x_1, ... , x_n). Y 同上
我想计算一个形状为 (n, 25) 的张量,其中每一列代表张量运算 f(x_i, y_j) 的输出,其中 f 对所有对象都是固定的1 <= i, j <= 5。操作 f 的输出形状为 (n, 1),就像 x_i 和 y_i.
我觉得有必要澄清一下,f 本质上是一个来自串联 [...x_i, ...y_i] 张量的全连接层,形状为 (1, 10 ), 到形状为 (1,5) 的输出层。
同样,很容易看出如何通过迭代和切片手动执行此操作。但是,这可能非常慢。分批执行此操作,其中张量 X、Y 现在具有形状 (n, 5, batch_size) 也是可取的,特别是对于小批量梯度下降。
这里很难说清楚为什么我想创建这个网络;我觉得它适合我的 'itemized tabular data' 领域,并且与完全连接的网络相比,每次操作的权重数量显着减少。
这可以使用 tensorflow 吗?当然不只是使用keras。 以下是根据 AloneTogether 的请求
在 numpy 中的示例import numpy as np
features = 16
batch_size = 256
X_batch = np.random.random((features, 5, batch_size))
Y_batch = np.random.random((features, 5, batch_size))
# one tensor operation to reduce weights in this custom 'layer'
f = np.random.random((features, 2 * features))
for b in range(batch_size):
X = X_batch[:, :, b]
Y = Y_batch[:, :, b]
for i in range(5):
x_i = X[:, i:i+1]
for j in range(5):
y_j = Y[:, j:j+1]
x_i_y_j = np.concatenate([x_i, y_j], axis=0)
# f(x_i, y_j)
# implemented by a fully-connected layer
f_i_j = np.matmul(f, x_i_y_j)
您需要的所有操作(串联和矩阵乘法)都可以进行批处理。
这里的困难部分是,您想要将 X 中所有项目的特征与 Y 中所有项目的特征(所有组合)连接起来。
我推荐的解决方案是将 X 的维度扩展到 [batch, features, 5, 1]
,将 Y 的维度扩展到 [batch, features, 1, 5]
比 tf.repeat()
两个张量所以它们的形状变成 [batch, features, 5, 5]
。
现在您可以连接 X 和 Y。您将得到一个形状为 [batch, 2*features, 5, 5]
的张量。观察以这种方式构建所有组合。
下一步是矩阵乘法。 tf.matmul()
也可以做批量矩阵乘法,但我在这里使用 tf.einsum()
因为我想更多地控制哪些维度被视为批量。
完整代码:
import tensorflow as tf
import numpy as np
batch_size=3
features=6
items=5
x = np.random.uniform(size=[batch_size,features,items])
y = np.random.uniform(size=[batch_size,features,items])
f = np.random.uniform(size=[2*features,features])
x_reps= tf.repeat(x[:,:,:,tf.newaxis], items, axis=3)
y_reps= tf.repeat(y[:,:,tf.newaxis,:], items, axis=2)
xy_conc = tf.concat([x_reps,y_reps], axis=1)
f_i_j = tf.einsum("bfij, fg->bgij", xy_conc,f)
f_i_j = tf.reshape(f_i_j , [batch_size,features,items*items])