Here's my setup:
indices = tf.placeholder(tf.int32, shape=[2])
weights = tf.Variable(tf.random_normal([100000, 3], stddev=0.35))
def objective(indices, weights):
idx1 = indices[0]; idx2 = indices[1] #extract two indices
mask = np.zeros(weights.shape.as_list()[0]) #builds a mask for some tensor "weights"
mask[idx1] = 1 # don't ask why I want to do this. I just do.
mask[idx2] = 1
obj = tf.reduce_sum(tf.multiply(weights[idx1], weights[idx2]))
return obj
optimizer = tf.train.GradientDescentOptimizer(0.01)
obj = objective(indices, weights)
trainer = optimizer.minimize(obj)
with tf.Session() as sess:
sess.run(tf.global_variables_initializer())
sess.run([trainer, obj], feed_dict={indices=[100, 1000]})
So the point is that I have some tensor, and I take a slice of it which corresponds to an index in my mask. This index is a tf.strided_slice. I want to index my mask with idx1 and idx2, as both evaluate to be ints.
But idx1 and idx2 are not ints but tensors, so the obj = objective(indices, weights) call leads to an error.
How can I get the code to work?
You can make use of a combination of tf.SparseTensor and tf.sparse_tensor_to_dense to achieve what you want:
import numpy as np
import tensorflow as tf
indices = tf.placeholder(tf.int64, shape=[2])
weights = tf.Variable(tf.random_normal([5, 3], stddev=0.35))
def objective(indices, weights):
idx1 = indices[0]; idx2 = indices[1] #extract two indices
mask = np.zeros(weights.shape.as_list()[0]) #builds a mask for some tensor "weights"
mask_ones = tf.SparseTensor(tf.reshape(indices, [-1,1]), [1, 1], mask.shape) # Stores the 1s used in the mask
mask = mask + tf.sparse_tensor_to_dense(mask_ones) # Set the mask
obj = tf.reduce_sum(tf.multiply(weights[idx1], weights[idx2]))
return obj, mask
obj, mask = objective(indices, weights)
with tf.Session() as sess:
sess.run(tf.global_variables_initializer())
print(sess.run([weights, obj, mask], feed_dict={indices:[0, 4]}))
[array([[...]], dtype=float32), 0.0068909675, array([1., 0., 0., 0., 1.], dtype=int32)]
Related
I want to elementwise multiply a dense tensor with shape [n, n, k] with a sparse tensor that has the shape [n, n, 1]. I want the values from the sparse tensor to repeat along the axis with the size s, like it would do if I used a dense tensor instead and relied on implicit broadcasting.
However the SparseTensor.__mul__ operation does not support broadcasting the sparse operand. I didn't find an operator to explicitly broadcast the sparse Tensor. How could I achieve this?
If you do not want to just convert the sparse tensor to dense, you can extract select the right values from the dense tensor to build a sparse result directly, something like this:
import tensorflow as tf
import numpy as np
with tf.Graph().as_default(), tf.Session() as sess:
# Input data
x = tf.placeholder(tf.float32, shape=[None, None, None])
y = tf.sparse.placeholder(tf.float32, shape=[None, None, 1])
# Indices of sparse tensor without third index coordinate
indices2 = y.indices[:, :-1]
# Values of dense tensor corresponding to sparse tensor values
x_sp = tf.gather_nd(x, indices2)
# Values of the resulting sparse tensor
res_vals = tf.reshape(x_sp * tf.expand_dims(y.values, 1), [-1])
# Shape of the resulting sparse tensor
res_shape = tf.shape(x, out_type=tf.int64)
# Make sparse tensor indices
k = res_shape[2]
v = tf.size(y.values)
# Add third coordinate to existing sparse tensor coordinates
idx1 = tf.tile(tf.expand_dims(indices2, 1), [1, k, 1])
idx2 = tf.tile(tf.range(k), [v])
res_idx = tf.concat([tf.reshape(idx1, [-1, 2]), tf.expand_dims(idx2, 1)], axis=1)
# Make sparse result
res = tf.SparseTensor(res_idx, res_vals, res_shape)
# Dense value for testing
res_dense = tf.sparse.to_dense(res)
# Dense operation for testing
res_dense2 = x * tf.sparse.to_dense(y)
# Test
x_val = np.arange(48).reshape(4, 4, 3)
y_val = tf.SparseTensorValue([[0, 0, 0], [2, 3, 0], [3, 1, 0]], [1, 2, 3], [4, 4, 1])
res_dense_val, res_dense2_val = sess.run((res_dense, res_dense2),
feed_dict={x: x_val, y: y_val})
print(np.allclose(res_dense_val, res_dense2_val))
# True
We need to sample values from one tensor regarding to another tensor that contains probabilities. Lets say, we have two tensors t1,t2 of shape (?,3), and want to find another tensor t3 of shape (?,1) that contains a sample of each row in t1 regarding to probabilities in t2.
You do this in two steps. First, you sample indices 0, 1 and 2, then you replace those indices with tensor values. This can be done with tf.random.categorical (see this question for more information about this function). Note tf.random.categorical was added in version 1.13.1.
import tensorflow as tf
with tf.Graph().as_default(), tf.Session() as sess:
tf.random.set_random_seed(0)
values = tf.placeholder(tf.float32, [None, 3])
probabilities = tf.placeholder(tf.float32, [None, 3])
# You can change the number of samples per row (or make it a placeholder)
num_samples = 1
# Use log to get log-probabilities or give logit values (pre-softmax) directly
logits = tf.log(probabilities)
# Sample column indices
col_idx = tf.random.categorical(logits, num_samples, dtype=tf.int32)
# Make row indices
num_rows = tf.shape(values)[0]
row_idx = tf.tile(tf.expand_dims(tf.range(num_rows), 1), (1, num_samples))
# Gather actual values
result = tf.gather_nd(values, tf.stack([row_idx, col_idx], axis=-1))
# Test
print(sess.run(result, feed_dict={
values: [[10., 20., 30.], [40., 50., 60.]],
# Can be actual or "proportional" probabilities not summing 1
probabilities: [[.1, .3, .6], [0., 4., 2.]]
}))
# [[30.]
# [60.]]
I am not really experienced in Tensorflow and I am doing one of those things that would apparently be very easy, but getting stuck at it.
I need to create a matrix given an input using a tensorflow layer.
Here is what I've gotten:
def createTransformationMatrix(args):
scale = args[0]
M = tf.Variable([scale[0], 0, 0, 0, scale[1], 0, 0, 0], dtype=tf.float32)
return M
scaleValue = Input(shape=(2,));
createTransfMatrix = Lambda(createTransformationMatrix)(scaleValue)
transformImage = Model([scaleValue], createTransfMatrix, name='transformImage');
scaleValueInput = np.array([1.0,1.0])
output = transformImage.predict(scaleValueInput[None,:])
This gives the error:
InvalidArgumentError (see above for traceback): You must feed a value for placeholder tensor 'lambda_1/Placeholder' with dtype float and shape [?,2]
[[Node: lambda_1/Placeholder = Placeholder[dtype=DT_FLOAT, shape=[?,2], _device="/job:localhost/replica:0/task:0/device:CPU:0"]()]]
You can do it using tensorflow
scaleValue = tf.placeholder("float32", 2)
b = tf.expand_dims(scaleValue, axis=1)
c = tf.constant([[1,0,0,0]], 'float32')
d = tf.matmul(b,c)
res = tf.reshape(d, shape=[-1])
with tf.Session() as sess:
print (sess.run([res], feed_dict={scaleValue: np.array([1,3])}))
Output
[array([1., 0., 0., 0., 3., 0., 0., 0.], dtype=float32)]
Solution using padding
scaleValue = tf.placeholder("float32", 2)
a = tf.expand_dims(scaleValue, axis=1)
paddings = tf.constant([[0, 0,], [0, 3]])
b = tf.pad(a, paddings, "CONSTANT")
res = tf.reshape(b, shape=[-1])
with tf.Session() as sess:
print (sess.run([res], feed_dict={scaleValue: np.array([1,3])}))
Set the padding to constant to the shape you want
Where in paddings = tf.constant([[top, bottom,], [left, right]]), top, bottom, left, right represents No:of zeros in the corresponding position.
I have a tensor A of shape (2, 4, 2), and a tensor B of shape (4, 4), all the values are int. Entries in A are from 0 to 3.
I want to create a tensor C of shape(2, 4, 2).
The for loop code is like:
for i in range(2):
for j in range(2):
for k in range(4):
C[i][k][j] = B[k][A[i][k][j]]
How can I create such tensor C in tensorflow?
Thanks.
Here is how you can do it with tf.gather_nd:
import tensorflow as tf
# Input values
A = tf.placeholder(tf.int32, [None, None, None])
B = tf.placeholder(tf.int32, [None, None])
# Make indices for first dimension of B
idx = tf.range(tf.shape(B)[0], dtype=A.dtype)[tf.newaxis, :, tf.newaxis]
# Tile first dimension indices to match the size of A
idx = tf.tile(idx, (tf.shape(A)[0], 1, tf.shape(A)[2]))
# Stack first dimension indices with A to complete index tensor
idx = tf.stack([idx, A], axis=-1)
# Make result gathering from B
C = tf.gather_nd(B, idx)
Here is an example, testing that the result matches your code:
import tensorflow as tf
import numpy as np
# Non-TensorFlow implementation for result comparison
A_value = np.random.randint(0, 4, size=(2, 4, 2))
B_value = np.random.randint(100, size=(4, 4))
C_value = np.empty(A_value.shape, dtype=B_value.dtype)
for i in range(A_value.shape[0]):
for j in range(A_value.shape[2]):
for k in range(A_value.shape[1]):
C_value[i][k][j] = B_value[k][A_value[i][k][j]]
# TensorFlow implementation
A = tf.placeholder(tf.int32, [None, None, None])
B = tf.placeholder(tf.int32, [None, None])
idx = tf.range(tf.shape(B)[0], dtype=A.dtype)[tf.newaxis, :, tf.newaxis]
idx = tf.tile(idx, (tf.shape(A)[0], 1, tf.shape(A)[2]))
idx = tf.stack([idx, A], axis=-1)
C = tf.gather_nd(B, idx)
# Check result
with tf.Session() as sess:
C_value_tf = sess.run(C, feed_dict={A: A_value, B: B_value})
print(np.all(np.equal(C_value_tf, C_value)))
Output:
True
I simply can't find the issue with tensorflow. Should be something simple. The example (simple XOR with noise classification) below raises the following issue:
ValueError: Passed Tensor("training_loss:0", shape=(), dtype=float32) should have graph attribute that is equal to current graph <tensorflow.python.framework.ops.Graph object at 0x0000018F142D9AC8>.
I simply do not see the problem.
import numpy as np
import pandas as pd
import tensorflow as tf
def xor_data():
np.random.seed(423)
rows = 1000
base_cases = [(1, 1, 0), (0, 0, 1), (1, 0, 1), (0, 1, 1)]
frames = list()
for case in base_cases:
tmp_df = pd.DataFrame(
np.random.uniform(low=-0.3, high=0.3, size=(rows, 2)),
columns=['x_1', 'x_2'])
tmp_df['x_1'] += case[0]
tmp_df['x_2'] += case[1]
tmp_df['y'] = case[2]
frames.append(tmp_df)
return pd.concat(frames, ignore_index=True)
def xor_fun():
x_1 = tf.contrib.layers.real_valued_column("x_1")
x_2 = tf.contrib.layers.real_valued_column("x_2")
model = tf.contrib.learn.DNNClassifier(hidden_units=[2,2 ],
feature_columns=[x_1, x_2])
df = xor_data()
feature_cols = {
'x_1': tf.constant(value=df['x_1'].values),
'x_2': tf.constant(value=df['x_2'].values)}
labels = tf.constant(value=df['y'].values)
def input_fn():
return feature_cols, labels
model.fit(input_fn=input_fn, steps=50)
if __name__ == '__main__':
xor_fun()
Returning the features or labels from a closure fails because a new tf.Graph is created when you call model.fit, so any modifications to the graph (e.g. tf.contrib calls) need to be made from within the input_fn (and therefore after the new graph has been instantiated).
To demonstrate, this works
import numpy as np
import tensorflow as tf
def input_fn():
x = np.array([1., 2., 3., 4.])
y = np.array([0., -1., -2., -3.])
feature_cols = {'x': tf.constant(x)}
labels = tf.constant(y)
return feature_cols, labels
features = [tf.contrib.layers.real_valued_column("x", dimension=1)]
estimator = tf.contrib.learn.LinearRegressor(feature_columns=features)
estimator.fit(input_fn=input_fn, steps=100)
print(estimator.evaluate(input_fn=input_fn, steps=1))
but this doesn't
import numpy as np
import tensorflow as tf
x = np.array([1., 2., 3., 4.])
y = np.array([0., -1., -2., -3.])
feature_cols = {'x': tf.constant(x)}
labels = tf.constant(y)
input_fn = lambda: feature_cols, labels
features = [tf.contrib.layers.real_valued_column("x", dimension=1)]
estimator = tf.contrib.learn.LinearRegressor(feature_columns=features)
estimator.fit(input_fn=input_fn, steps=100)
print(estimator.evaluate(input_fn=input_fn, steps=1))
See also this answer https://stackoverflow.com/a/39400592/6536722
While I'm not entirely sure what is going on, my guess is that feature_cols and labels from input_fn doesn't belong to the graph that is generated from the DNNClassifier. Following https://github.com/tensorflow/tensorflow/blob/master/tensorflow/examples/tutorials/input_fn/boston.py, I modified xor_fun() a little bit below. This is for v0.11
features = ['x_1','x_2']
label ='y'
df = xor_data()
x_1 = tf.contrib.layers.real_valued_column("x_1")
x_2 = tf.contrib.layers.real_valued_column("x_2")
model = tf.contrib.learn.DNNClassifier(hidden_units=[2,2 ],
feature_columns=[x_1, x_2],
n_classes=3)
feature_cols = [tf.contrib.layers.real_valued_column(k)
for k in features]
def input_fn(data_set):
feature_cols = {k: tf.constant(data_set[k].values) for k in features}
labels = tf.constant(data_set[label].values)
return feature_cols, labels
model.fit(input_fn=lambda: input_fn(df), steps=50)