Static function to check if given info will lead to a valid configuration of CLFullyConnectedLayer
349{
350 ARM_COMPUTE_RETURN_ERROR_ON_NULLPTR(input, weights, output);
351 ARM_COMPUTE_RETURN_ERROR_ON_DATA_TYPE_CHANNEL_NOT_IN(input, 1, DataType::QASYMM8, DataType::F16,
352 DataType::F32);
353 ARM_COMPUTE_RETURN_ERROR_ON_MISMATCHING_DATA_TYPES(input, weights, output);
354 ARM_COMPUTE_RETURN_ERROR_ON(weights->num_dimensions() > 2);
355
356 bool weights_reshaped = fc_info.transpose_weights ? fc_info.are_weights_reshaped : true;
357 bool is_fc_after_conv = true;
358
359 const ITensorInfo &flatten_input =
360 TensorInfo(
input->clone()->set_is_resizable(
true).reset_padding().set_tensor_shape(
361 compute_flatten_shape(input)));
362 const ITensorInfo &reshaped_weights =
363 TensorInfo(weights->clone()->set_is_resizable(true).reset_padding().set_tensor_shape(
364 compute_transposed_shape(*weights)));
365 const ITensorInfo &converted_weights =
366 weights_reshaped ? TensorInfo(weights->clone()->set_is_resizable(true).reset_padding())
367 : TensorInfo(*reshaped_weights.
clone());
368
369
370
371
372
373
374
375 const ITensorInfo *input_to_use =
input;
376 const ITensorInfo *weights_to_use = weights;
377
378
379 const bool is_batched_fc_layer =
output->dimension(1) > 1;
380 if (is_batched_fc_layer)
381 {
382 is_fc_after_conv = (TensorShape::num_max_dimensions >= 4) &&
383 (std::equal(
input->tensor_shape().cbegin() + 3,
input->tensor_shape().cend(),
384 output->tensor_shape().cbegin() + 1));
385 }
386 else
387 {
388 is_fc_after_conv =
input->num_dimensions() > 1;
389 }
390
391 if (!weights_reshaped)
392 {
393
394 ARM_COMPUTE_RETURN_ON_ERROR(CLTranspose::validate(weights, &reshaped_weights));
395 weights_to_use = &reshaped_weights;
396 }
397
398 if (is_fc_after_conv && (
input->data_layout() != fc_info.weights_trained_layout))
399 {
400
401 ARM_COMPUTE_RETURN_ON_ERROR(CLConvertFullyConnectedWeights::validate(
402 weights_to_use, &converted_weights,
input->tensor_shape(), fc_info.weights_trained_layout));
403 weights_to_use = &converted_weights;
404 }
405
406 if (is_fc_after_conv)
407 {
408
409 ARM_COMPUTE_RETURN_ERROR_ON(
410 (weights_to_use->dimension(1) !=
412
413
414 ARM_COMPUTE_RETURN_ON_ERROR(CLFlattenLayer::validate(input, &flatten_input));
415 input_to_use = &flatten_input;
416 }
417 else
418 {
419
420 ARM_COMPUTE_RETURN_ERROR_ON(
input->dimension(0) != weights_to_use->dimension(1));
421 }
422
423
424 ARM_COMPUTE_RETURN_ON_ERROR(
425 validate_mm(*input_to_use, *weights_to_use, biases, *output, fc_info));
426
427 return Status{};
428}
luci::CircleConst * clone(luci::CircleConst *node)
Return cloned object of CircleConst node.