use of com.yahoo.searchlib.rankingexpression.rule.ExpressionNode in project vespa by vespa-engine.
the class TensorFlowFeatureConverter method reduceBatchDimensions.
/**
* Check if batch dimensions of inputs can be reduced out. If the input
* macro specifies that a single exemplar should be evaluated, we can
* reduce the batch dimension out.
*/
private void reduceBatchDimensions(RankingExpression expression, TensorFlowModel model, RankProfile profile, QueryProfileRegistry queryProfiles) {
TypeContext<Reference> typeContext = profile.typeContext(queryProfiles);
TensorType typeBeforeReducing = expression.getRoot().type(typeContext);
// Check generated macros for inputs to reduce
Set<String> macroNames = new HashSet<>();
addMacroNamesIn(expression.getRoot(), macroNames, model);
for (String macroName : macroNames) {
if (!model.macros().containsKey(macroName)) {
continue;
}
RankProfile.Macro macro = profile.getMacros().get(macroName);
if (macro == null) {
throw new IllegalArgumentException("Model refers to generated macro '" + macroName + "but this macro is not present in " + profile);
}
RankingExpression macroExpression = macro.getRankingExpression();
macroExpression.setRoot(reduceBatchDimensionsAtInput(macroExpression.getRoot(), model, typeContext));
}
// Check expression for inputs to reduce
ExpressionNode root = expression.getRoot();
root = reduceBatchDimensionsAtInput(root, model, typeContext);
TensorType typeAfterReducing = root.type(typeContext);
root = expandBatchDimensionsAtOutput(root, typeBeforeReducing, typeAfterReducing);
expression.setRoot(root);
}
use of com.yahoo.searchlib.rankingexpression.rule.ExpressionNode in project vespa by vespa-engine.
the class TensorFlowFeatureConverter method expandBatchDimensionsAtOutput.
/**
* If batch dimensions have been reduced away above, bring them back here
* for any following computation of the tensor.
* Todo: determine when this is not necessary!
*/
private ExpressionNode expandBatchDimensionsAtOutput(ExpressionNode node, TensorType before, TensorType after) {
if (after.equals(before)) {
return node;
}
TensorType.Builder typeBuilder = new TensorType.Builder();
for (TensorType.Dimension dimension : before.dimensions()) {
if (dimension.size().orElse(-1L) == 1 && !after.dimensionNames().contains(dimension.name())) {
typeBuilder.indexed(dimension.name(), 1);
}
}
TensorType expandDimensionsType = typeBuilder.build();
if (expandDimensionsType.dimensions().size() > 0) {
ExpressionNode generatedExpression = new ConstantNode(new DoubleValue(1.0));
Generate generatedFunction = new Generate(expandDimensionsType, new GeneratorLambdaFunctionNode(expandDimensionsType, generatedExpression).asLongListToDoubleOperator());
Join expand = new Join(TensorFunctionNode.wrapArgument(node), generatedFunction, ScalarFunctions.multiply());
return new TensorFunctionNode(expand);
}
return node;
}
use of com.yahoo.searchlib.rankingexpression.rule.ExpressionNode in project vespa by vespa-engine.
the class ConstantTensorTransformer method transformArguments.
private ExpressionNode transformArguments(ReferenceNode node, RankProfileTransformContext context) {
List<ExpressionNode> arguments = node.getArguments().expressions();
List<ExpressionNode> transformedArguments = new ArrayList<>(arguments.size());
for (ExpressionNode argument : arguments) {
transformedArguments.add(transform(argument, context));
}
return node.setArguments(transformedArguments);
}
use of com.yahoo.searchlib.rankingexpression.rule.ExpressionNode in project vespa by vespa-engine.
the class Reshape method reshape.
public static TensorFunction reshape(TensorFunction inputFunction, TensorType inputType, TensorType outputType) {
if (!tensorSize(inputType).equals(tensorSize(outputType))) {
throw new IllegalArgumentException("New and old shape of tensor must have the same size when reshaping");
}
// Conceptually, reshaping consists on unrolling a tensor to an array using the dimension order,
// then use the dimension order of the new shape to roll back into a tensor.
// Here we create a transformation tensor that is multiplied with the from tensor to map into
// the new shape. We have to introduce temporary dimension names and rename back if dimension names
// in the new and old tensor type overlap.
ExpressionNode unrollFrom = unrollTensorExpression(inputType);
ExpressionNode unrollTo = unrollTensorExpression(outputType);
ExpressionNode transformExpression = new ComparisonNode(unrollFrom, TruthOperator.EQUAL, unrollTo);
TensorType transformationType = new TensorType.Builder(inputType, outputType).build();
Generate transformTensor = new Generate(transformationType, new GeneratorLambdaFunctionNode(transformationType, transformExpression).asLongListToDoubleOperator());
TensorFunction outputFunction = new Reduce(new com.yahoo.tensor.functions.Join(inputFunction, transformTensor, ScalarFunctions.multiply()), Reduce.Aggregator.sum, inputType.dimensions().stream().map(TensorType.Dimension::name).collect(Collectors.toList()));
return outputFunction;
}
use of com.yahoo.searchlib.rankingexpression.rule.ExpressionNode in project vespa by vespa-engine.
the class TensorFlowOperation method function.
/**
* Returns the Vespa tensor function implementing all operations from this node with inputs
*/
public Optional<TensorFunction> function() {
if (function == null) {
if (isConstant()) {
ExpressionNode constant = new ReferenceNode(Reference.simple("constant", vespaName()));
function = new TensorFunctionNode.TensorFunctionExpressionNode(constant);
} else if (outputs.size() > 1) {
macro = lazyGetFunction();
function = new VariableTensor(macroName(), type.type());
} else {
function = lazyGetFunction();
}
}
return Optional.ofNullable(function);
}
Aggregations