tensorflow / tensorflow/java

Ability to convert Tensor to String representation

Aperta
#268 3 commenti 0 reazioni 0 assegnatari Vedi su GitHub

Nessuno ha ancora preso questa issue.

Lingua principale
Java
Stelle
928
Fork
227
Metriche di merge delle PR
Nessuna PR unita negli ultimi 30g

Descrizione

Per our discussion on Gitter, here is a possible implementation for converting Tensors to a String representation. It is still missing some important features, like collapsing long arrays using ellipses, but this can serve as a stepping stone. The functionality is meant to ease troubleshooting/debugging so performance should not be an issue.

import org.tensorflow.Session;
import org.tensorflow.ndarray.Shape;
import org.tensorflow.ndarray.buffer.DataBuffer;
import org.tensorflow.ndarray.buffer.DoubleDataBuffer;
import org.tensorflow.ndarray.buffer.FloatDataBuffer;
import org.tensorflow.ndarray.buffer.IntDataBuffer;
import org.tensorflow.ndarray.buffer.LongDataBuffer;
import org.tensorflow.ndarray.buffer.ShortDataBuffer;
import org.tensorflow.types.TFloat16;
import org.tensorflow.types.TFloat32;
import org.tensorflow.types.TFloat64;
import org.tensorflow.types.TInt32;
import org.tensorflow.types.TInt64;
import org.tensorflow.types.TUint8;

import java.util.StringJoiner;

public final class Tensors
{
	private final Session session;

	/**
	 * @param session the session used by all operations
	 */
	public Tensors(Session session)
	{
		this.session = session;
	}

	/**
	 * @param tensor a tensor
	 * @return the String representation of the tensor
	 */
	public String toString(TFloat64 tensor)
	{
		Shape shape = tensor.shape();
		DoubleDataBuffer doubles = tensor.asRawTensor().data().asDoubles();
		return toString(doubles, shape, 0, 0, tensor.rank()).text;
	}

	/**
	 * @param tensor a tensor
	 * @return the String representation of the tensor
	 */
	public String toString(TFloat32 tensor)
	{
		Shape shape = tensor.shape();
		FloatDataBuffer doubles = tensor.asRawTensor().data().asFloats();
		return toString(doubles, shape, 0, 0, tensor.rank()).text;
	}

	/**
	 * @param tensor a tensor
	 * @return the String representation of the tensor
	 */
	public String toString(TFloat16 tensor)
	{
		Shape shape = tensor.shape();
		FloatDataBuffer doubles = tensor.asRawTensor().data().asFloats();
		return toString(doubles, shape, 0, 0, tensor.rank()).text;
	}

	/**
	 * @param tensor a tensor
	 * @return the String representation of the tensor
	 */
	public String toString(TInt64 tensor)
	{
		Shape shape = tensor.shape();
		LongDataBuffer doubles = tensor.asRawTensor().data().asLongs();
		return toString(doubles, shape, 0, 0, tensor.rank()).text;
	}

	/**
	 * @param tensor a tensor
	 * @return the String representation of the tensor
	 */
	public String toString(TInt32 tensor)
	{
		Shape shape = tensor.shape();
		IntDataBuffer doubles = tensor.asRawTensor().data().asInts();
		return toString(doubles, shape, 0, 0, tensor.rank()).text;
	}

	/**
	 * @param tensor a tensor
	 * @return the String representation of the tensor
	 */
	public String toString(TUint8 tensor)
	{
		Shape shape = tensor.shape();
		ShortDataBuffer doubles = tensor.asRawTensor().data().asShorts();
		return toString(doubles, shape, 0, 0, tensor.rank()).text;
	}

	/**
	 * @param data      the data
	 * @param shape     the shape of the tensor
	 * @param index     the index of the tensor element to start at
	 * @param dimension the current dimension
	 * @param rank      the maximum dimension
	 * @return the String representation of the {@code dimension}
	 */
	private ToStringResponse toString(DataBuffer<?> data, Shape shape, int index, int dimension, int rank)
	{
		int numElements = 0;
		StringJoiner joiner;
		if (dimension < rank)
		{
			joiner = new StringJoiner(",\n", "\t".repeat(dimension) + "[\n", "\n" + "\t".repeat(dimension) + "]");
			for (long i = 0, size = shape.size(rank - 1); i < size; ++i)
			{
				ToStringResponse response = toString(data, shape, index, dimension + 1, rank);
				joiner.add(response.text);
				numElements += response.numElements;
				index += response.numElements;
			}
		}
		else
		{
			joiner = new StringJoiner(",", "\t".repeat(dimension) + "[", "]");
			for (long i = 0, size = shape.size(rank - 1); i < size; ++i)
			{
				joiner.add(String.valueOf(data.getObject(index)));
				++numElements;
				++index;
			}
		}
		return new ToStringResponse(joiner.toString(), numElements);
	}

	/**
	 * @param text        the string representation of a tensor dimension
	 * @param numElements the number of elements contained in {@code text}
	 */
	private record ToStringResponse(String text, int numElements)
	{
	}
}

Guida per i contributori

Apri la guida per i contributori

Come iniziare

  1. Leggi tutta la issue e poi la guida ai contributi del progetto.
  2. Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
  3. Fai un fork del repository e lavora su un branch.
  4. Apri una pull request che faccia riferimento al numero della issue.

Direzione di ricerca

La issue contiene un’implementazione proposta di Tensors che usa Session, classi dei tipi tensor e le API Shape e DataBuffer, ma non indica alcun file del repository né alcun test. Inizia individuando i punti di ingresso esistenti per i tensor e la conversione in stringa, quindi esamina la proposta e il comportamento mancante di raggruppamento degli array lunghi. Il lavoro è completato quando i tipi tensor supportati hanno una rappresentazione in stringa concordata e testata.

Scritto dal modello di indicizzazione a partire dal testo della issue.

Valutazione

Stack tecnologico
java
Ambito
machine-learning
Tipo di issue
Funzionalità
Difficoltà
4/5
Tempo stimato
3-5 giorni
Stato di attività
Ferma
Chiarezza
Abbastanza chiara
Idoneità per principianti
35/100

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.