如何从TensorFlow中的3-D Tensor中选择行?

时间:2016-03-18 15:27:59

标签: tensorflow

我有一个尺寸为import java.util.function.Function; import javafx.application.Application; import javafx.beans.property.Property; import javafx.beans.property.SimpleStringProperty; import javafx.beans.property.StringProperty; import javafx.geometry.Insets; import javafx.scene.Scene; import javafx.scene.control.Label; import javafx.scene.control.TableCell; import javafx.scene.control.TableColumn; import javafx.scene.control.TableView; import javafx.scene.layout.BorderPane; import javafx.stage.Stage; public class HoverTableCells extends Application { @Override public void start(Stage primaryStage) { TableView<Person> table = new TableView<>(); TableColumn<Person, String> firstNameCol = column("First Name", Person::firstNameProperty); TableColumn<Person, String> lastNameCol = column("Last Name", Person::lastNameProperty); TableColumn<Person, String> emailCol = column("Email", Person::emailProperty); StringProperty hoveredProperty = new SimpleStringProperty(); firstNameCol.setCellFactory(tc -> new HoverCell(hoveredProperty)); lastNameCol.setCellFactory(tc -> new HoverCell(hoveredProperty)); emailCol.setCellFactory(tc -> new HoverCell(hoveredProperty)); Label currentHover = new Label(); currentHover.textProperty().bind(hoveredProperty); table.getColumns().add(firstNameCol); table.getColumns().add(lastNameCol); table.getColumns().add(emailCol); table.getItems().addAll( new Person("Jacob", "Smith", "jacob.smith@example.com"), new Person("Isabella", "Johnson", "isabella.johnson@example.com"), new Person("Ethan", "Williams", "ethan.williams@example.com"), new Person("Emma", "Jones", "emma.jones@example.com"), new Person("Michael", "Brown", "michael.brown@example.com") ); BorderPane root = new BorderPane(table); BorderPane.setMargin(currentHover, new Insets(10)); root.setTop(currentHover); Scene scene = new Scene(root, 600, 600); primaryStage.setScene(scene); primaryStage.show(); } private static <S,T> TableColumn<S,T> column(String title, Function<S, Property<T>> property) { TableColumn<S, T> col = new TableColumn<>(title); col.setCellValueFactory(cellData -> property.apply(cellData.getValue())); return col ; } public static class HoverCell extends TableCell<Person, String> { public HoverCell(StringProperty hoverProperty) { setOnMouseEntered(e -> hoverProperty.set(getItem())); setOnMouseExited(e -> hoverProperty.set(null)); } @Override protected void updateItem(String item, boolean empty) { super.updateItem(item, empty); setText(empty ? null : item); } } public static class Person { private final StringProperty firstName = new SimpleStringProperty(); private final StringProperty lastName = new SimpleStringProperty(); private final StringProperty email = new SimpleStringProperty(); public Person(String firstName, String lastName, String email) { setFirstName(firstName); setLastName(lastName); setEmail(email); } public final StringProperty firstNameProperty() { return this.firstName; } public final String getFirstName() { return this.firstNameProperty().get(); } public final void setFirstName(final String firstName) { this.firstNameProperty().set(firstName); } public final StringProperty lastNameProperty() { return this.lastName; } public final String getLastName() { return this.lastNameProperty().get(); } public final void setLastName(final String lastName) { this.lastNameProperty().set(lastName); } public final StringProperty emailProperty() { return this.email; } public final String getEmail() { return this.emailProperty().get(); } public final void setEmail(final String email) { this.emailProperty().set(email); } } public static void main(String[] args) { launch(args); } } 的张量Table 1 insert 1 record Table 2 insert 1 record using the Table 1's id (key) Table 3 insert 20 records using the Table 2's id Table 1 insert 1 record Table 2 insert 1 record using the Table 1's second record's id Table 3 insert 20 records using the Table 2's second record's id (即批次中的每个logit都是一个矩阵)。在我的情况下,批量大小为2,有4行和4个坐标。

logits

我想选择第一批的第一行和第二行以及第二批的第二行和第四行。

[batch_size, num_rows, num_coordinates]

所以期望的输出是

logits = tf.constant([[[10.0, 10.0, 20.0, 20.0],
                      [11.0, 10.0, 10.0, 30.0],
                      [12.0, 10.0, 10.0, 20.0],
                      [13.0, 10.0, 10.0, 20.0]],
                     [[14.0, 11.0, 21.0, 31.0],
                      [15.0, 11.0, 11.0, 21.0],
                      [16.0, 11.0, 11.0, 21.0],
                      [17.0, 11.0, 11.0, 21.0]]])

如何使用TensorFlow执行此操作?我尝试使用indices = tf.constant([[0, 1], [1, 3]]) ,但它没有返回我的预期。谢谢!

2 个答案:

答案 0 :(得分:7)

这在TensorFlow中是可行的,但稍微不方便,因为tf.gather()目前仅适用于一维索引,并且仅从张量的第0维选择切片。但是,仍然可以通过转换参数来有效地解决您的问题,以便将它们传递给tf.gather()

logits = ... # [2 x 4 x 4] tensor
indices = tf.constant([[0, 1], [1, 3]])

# Use tf.shape() to make this work with dynamic shapes.
batch_size = tf.shape(logits)[0]
rows_per_batch = tf.shape(logits)[1]
indices_per_batch = tf.shape(indices)[1]

# Offset to add to each row in indices. We use `tf.expand_dims()` to make 
# this broadcast appropriately.
offset = tf.expand_dims(tf.range(0, batch_size) * rows_per_batch, 1)

# Convert indices and logits into appropriate form for `tf.gather()`. 
flattened_indices = tf.reshape(indices + offset, [-1])
flattened_logits = tf.reshape(logits, tf.concat(0, [[-1], tf.shape(logits)[2:]]))

selected_rows = tf.gather(flattened_logits, flattened_indices)

result = tf.reshape(selected_rows,
                    tf.concat(0, [tf.pack([batch_size, indices_per_batch]),
                                  tf.shape(logits)[2:]]))

请注意,由于这使用tf.reshape()而不是tf.transpose(),因此不需要修改logits张量中的(可能很大)数据,因此它应该相当有效

答案 1 :(得分:4)

mrry的答案很棒,但我认为使用函数tf.gather_nd可以用更少的代码行解决问题(可能这个函数在mrry编写时尚未提供):

logits = tf.constant([[[10.0, 10.0, 20.0, 20.0],
                      [11.0, 10.0, 10.0, 30.0],
                      [12.0, 10.0, 10.0, 20.0],
                      [13.0, 10.0, 10.0, 20.0]],
                     [[14.0, 11.0, 21.0, 31.0],
                      [15.0, 11.0, 11.0, 21.0],
                      [16.0, 11.0, 11.0, 21.0],
                      [17.0, 11.0, 11.0, 21.0]]])

indices = tf.constant([[[0, 0], [0, 1]], [[1, 1], [1, 3]]])

result = tf.gather_nd(logits, indices)
with tf.Session() as sess:
    print(sess.run(result))

这将打印

[[[ 10.  10.  20.  20.]
  [ 11.  10.  10.  30.]]

 [[ 15.  11.  11.  21.]
  [ 17.  11.  11.  21.]]]
自v0.10起,

tf.gather_nd应该可用。查看this github issue以获取更多有关此问题的讨论。