Entw.: Tensorflow mit Delphi (3)

Die nach Delphi umgesetzte C-API wird mit DUnitX getestet. Dies ermöglicht einen automatisierten Schnelltest nach API-Änderungen. Dieser Artikel liefert komplette Delphi-Projekt des Testprogramms und die Delphi-API für die Tensorflow-Version 1.3.

Test der API mit DUnitX

Die folgende Delphi-Source zeigt einen Ausschnitt des Testprogramms.

procedure TTensorFlowBaseTests.Test_SetShape;
var
 l_iNumDims:  Integer;
 l_pStatus: PTF_Status;
 l_pGraph:  PTF_Graph;
 l_pFeed, l_pThree:   PTF_Operation;
 l_oOutput:   TF_Output;
 l_oThreeOut: PTF_Output;
 l_iDim:      TF_int64_t;
 l_arDims:    array of Int64;
 l_arDimsRet: array of TF_int64_t;
begin
 System.Writeln('Execute TTensorFlowBaseTests.Test_SetShape');

 l_pStatus := TF_NewStatus();
 l_pGraph  := TF_NewGraph();

 l_pFeed := uTestTensorFlowUtil.PlaceholderOp(l_pGraph, l_pStatus);
 Assert.AreEqual(Integer(TF_OK), Integer(TF_GetCode(l_pStatus)), 'Assertion failed: ' + TF_Message(l_pStatus));

 // Fetch the shape, it should be completely unknown.
 l_oOutput.oper := l_pFeed;
 l_oOutput.index:= 0;
 l_iNumDims := TF_GraphGetTensorNumDims(l_pGraph, l_oOutput, l_pStatus);
 Assert.AreEqual(Integer(TF_OK), Integer(TF_GetCode(l_pStatus)), 'Assertion failed: ' + TF_Message(l_pStatus));
 Assert.AreEqual(-1, l_iNumDims, 'Assertion failed: NumDims wrong!');

 // Set the shape to be 2 x Unknown
 l_arDims := [2, -1];
 TF_GraphSetTensorShape(l_pGraph, l_oOutput, PTF_int64_t(@l_arDims[0]), 2, l_pStatus);
 Assert.AreEqual(Integer(TF_OK), Integer(TF_GetCode(l_pStatus)), 'Assertion failed: ' + TF_Message(l_pStatus));

 // Fetch the shape and validate it is 2 by -1.
 l_iNumDims := TF_GraphGetTensorNumDims(l_pGraph, l_oOutput, l_pStatus);
 Assert.AreEqual(Integer(TF_OK), Integer(TF_GetCode(l_pStatus)), 'Assertion failed: ' + TF_Message(l_pStatus));
 Assert.AreEqual(2, l_iNumDims, 'Assertion failed: NumDims wrong!');

 // Resize the dimension vector appropriately.
 l_arDimsRet := [11, 12];
 TF_GraphGetTensorShape(l_pGraph, l_oOutput, PTF_int64_t(@l_arDimsRet[0]), 2, l_pStatus);
 Assert.AreEqual(Integer(TF_OK), Integer(TF_GetCode(l_pStatus)), 'Assertion failed: ' + TF_Message(l_pStatus));
 Assert.AreEqual(2, l_iNumDims, 'Assertion failed: NumDims wrong!');
 Assert.AreEqual(l_arDims[0], l_arDimsRet[0], 'Assertion failed: l_arDims[0] <> l_arDimsRet[0]');
 Assert.AreEqual(l_arDims[1], l_arDimsRet[1], 'Assertion failed: l_arDims[1] <> l_arDimsRet[1]');

 // Set to a new valid shape: [2, 3]
 l_arDims[1] := 3;
 TF_GraphSetTensorShape(l_pGraph, l_oOutput, PTF_int64_t(@l_arDims[0]), 2, l_pStatus);
 Assert.AreEqual(Integer(TF_OK), Integer(TF_GetCode(l_pStatus)), 'Assertion failed: ' + TF_Message(l_pStatus));

 // Fetch and see that the new value is returned.
 TF_GraphGetTensorShape(l_pGraph, l_oOutput, PTF_int64_t(@l_arDimsRet[0]), 2, l_pStatus);
 Assert.AreEqual(Integer(TF_OK), Integer(TF_GetCode(l_pStatus)), 'Assertion failed: ' + TF_Message(l_pStatus));
 Assert.AreEqual(l_arDims[0], l_arDimsRet[0], 'Assertion failed: l_arDims[0] <> l_arDimsRet[0]');
 Assert.AreEqual(l_arDims[1], l_arDimsRet[1], 'Assertion failed: l_arDims[1] <> l_arDimsRet[1]');

 // Try to set 'unknown' on the shape and see that
 // it doesn't change.
 l_arDims[0] := -1;
 l_arDims[1] := -1;
 TF_GraphSetTensorShape(l_pGraph, l_oOutput, PTF_int64_t(@l_arDims[0]), 2, l_pStatus);
 Assert.AreEqual(Integer(TF_OK), Integer(TF_GetCode(l_pStatus)), 'Assertion failed: ' + TF_Message(l_pStatus));
 // Fetch and see that the new value is returned.
 TF_GraphGetTensorShape(l_pGraph, l_oOutput, PTF_int64_t(@l_arDimsRet[0]), 2, l_pStatus);
 Assert.AreEqual(Integer(TF_OK), Integer(TF_GetCode(l_pStatus)), 'Assertion failed: ' + TF_Message(l_pStatus));
 Assert.AreEqual(TF_int64_t(2), l_arDimsRet[0], 'Assertion failed: l_arDims[0] <> l_arDimsRet[0]');
 Assert.AreEqual(TF_int64_t(3), l_arDimsRet[1], 'Assertion failed: l_arDims[1] <> l_arDimsRet[1]');

 // Try to fetch a shape with the wrong num_dims
 TF_GraphGetTensorShape(l_pGraph, l_oOutput, PTF_int64_t(@l_arDimsRet[0]), 5, l_pStatus);
 Assert.AreEqual(Integer(TF_INVALID_ARGUMENT), Integer(TF_GetCode(l_pStatus)), 'Assertion failed: ' + TF_Message(l_pStatus));

 // Try to set an invalid shape (cannot change 2x3 to a 2x5).
 l_arDims[1] := 5;
 TF_GraphSetTensorShape(l_pGraph, l_oOutput, PTF_int64_t(@l_arDims[0]), 2, l_pStatus);
 Assert.AreEqual(Integer(TF_INVALID_ARGUMENT), Integer(TF_GetCode(l_pStatus)), 'Assertion failed: ' + TF_Message(l_pStatus));

 // Test for a scalar.
 l_pThree := ScalarConstOp(3, l_pGraph, l_pStatus);
 Assert.AreEqual(Integer(TF_OK), Integer(TF_GetCode(l_pStatus)), 'Assertion failed: ' + TF_Message(l_pStatus));

 l_oThreeOut.oper := l_pThree;
 l_oThreeOut.index:= 0;
 l_iNumDims := TF_GraphGetTensorNumDims(l_pGraph, l_oThreeOut^, l_pStatus);
 Assert.AreEqual(Integer(TF_OK), Integer(TF_GetCode(l_pStatus)), 'Assertion failed: ' + TF_Message(l_pStatus));
 Assert.AreEqual(0, l_iNumDims, 'Assertion failed: l_iNumDims is not 0');
 TF_GraphGetTensorShape(l_pGraph, l_oThreeOut^, PTF_int64_t(@l_arDimsRet[0]), l_iNumDims, l_pStatus);
 Assert.AreEqual(Integer(TF_OK), Integer(TF_GetCode(l_pStatus)), 'Assertion failed: ' + TF_Message(l_pStatus));

 // Clean up
 TF_DeleteGraph(l_pGraph);
 TF_DeleteStatus(l_pStatus);
end;

Die komplette Testumgebung mit der Delphi-API finden Sie in meiner Github-Repository .