我有一个尺寸为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]])
,但它没有返回我的预期。谢谢!
答案 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以获取更多有关此问题的讨论。