Skip to content

Commit d9694c4

Browse files
CrichenRossHNPCericstj
authored
Updated Tensorflow.Net to 0.70.2 with Tensorflow 2.7.0. (#7472)
* Updated Tensorflow.Net to 0.70.2 with Tensorflow 2.7.0. NumSharp replaced with Tensorflow.NumPy. TensorShape replaced with Shape, Shape object has dimensions as 64 bit long, check added for casting to 32 bit int alsoTensor constructor using SafeTensorHandle/DangerousGetHandle and TF_DataType not required when casting. Added StringTensorFactory to wrap addition tensorflow.dll methods required to create Tensors from string based input. * Common code to ArrayUtils, dotnet added to Sdk install to resolve CI issues. * Temporarily omit GPU packages * Removing installation of .NET 9.0 * Update TensorFlow.NET to 0.150.0 * Rollback TensorFlow.NET to 0.110.1 to workaround strong name signing issue Tensorflow.NET stopped being strong name signed in 0.110.2. See SciSharp/TensorFlow.NET#1296 * Rollback TensorFlow.Net to 0.100.4 After this version a dependency was introduced on OneOf which is not strong name signed and breaks use on .NETFramework. * Rollback TensorFlow.Net to 0.100.2 We can't use newer than 0.100.4 due to strong naming issues. There's a bug in the Session.Dispose introduced by SciSharp/TensorFlow.NET@a7c9a75 (in 0.100.4) which was later fixed in SciSharp/TensorFlow.NET@58de537 but that's after the strong naming regression. * Use different version for TensorFlow GPU packages Workaround SciSharp/TensorFlow.NET#1294 * Remove VectorDataViewType overload that accepts long[] * Update Microsoft.ML.Samples.GPU.csproj * Workaround build error from TF-GPU package * Update src/Microsoft.ML.TensorFlow/TensorflowTransform.cs * Avoid finalizer crash in tests The TensorFlow.NET session finalizer has a bug where it will crash if run after the finalizer for the `tensorflow` type. Avoid that by ensuring we dispose all Session objects. * Fix a couple more missing dispose --------- Co-authored-by: Ross Halliday <[email protected]> Co-authored-by: Eric StJohn <[email protected]>
1 parent 71e1280 commit d9694c4

File tree

10 files changed

+235
-147
lines changed

10 files changed

+235
-147
lines changed

Directory.Packages.props

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,8 +42,8 @@
4242
<PackageVersion Include="Parquet.Net" Version="$(ParquetDotNetVersion)" />
4343
<PackageVersion Include="Plotly.NET.CSharp" Version="$(PlotlyNETCSharpVersion)" />
4444
<PackageVersion Include="SciSharp.TensorFlow.Redist" Version="$(TensorFlowVersion)" />
45-
<PackageVersion Include="SciSharp.TensorFlow.Redist-Linux-GPU" Version="$(TensorFlowVersion)" />
46-
<PackageVersion Include="SciSharp.TensorFlow.Redist-Windows-GPU" Version="$(TensorFlowVersion)" />
45+
<PackageVersion Include="SciSharp.TensorFlow.Redist-Linux-GPU" Version="$(TensorFlowLinuxGpuVersion)" />
46+
<PackageVersion Include="SciSharp.TensorFlow.Redist-Windows-GPU" Version="$(TensorFlowWindowsGpuVersion)" />
4747
<PackageVersion Include="SharpZipLib" Version="$(SharpZipLibVersion)" />
4848
<PackageVersion Include="SkiaSharp" Version="$(SkiaSharpVersion)" />
4949
<PackageVersion Include="SkiaSharp.NativeAssets.Linux.NoDependencies" Version="$(SkiaSharpVersion)" />

docs/samples/Microsoft.ML.Samples.GPU/Microsoft.ML.Samples.GPU.csproj

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -53,22 +53,27 @@
5353
<PackageReference Include="SciSharp.TensorFlow.Redist-Linux-GPU" />
5454
</ItemGroup>
5555

56-
<ItemGroup>
56+
<!-- workaround https://github.com/SciSharp/TensorFlow.NET/issues/1297 -->
57+
<Target Name="_EnsureObjFolder" BeforeTargets="FileRestitch">
58+
<MakeDir Directories="obj" />
59+
</Target>
60+
61+
<ItemGroup>
5762
<Content Include="$(ModelDownloadPath)\ResNet18Onnx\ResNet18.onnx">
5863
<Link>DnnImageModels\ResNet18Onnx\ResNet18.onnx</Link>
5964
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
6065
</Content>
6166
</ItemGroup>
6267

63-
<ItemGroup>
68+
<ItemGroup>
6469
<Content Include="$(ModelDownloadPath)\ResNetPrepOnnx\ResNetPreprocess.onnx">
6570
<Link>DnnImageModels\ResNetPrepOnnx\ResNetPreprocess.onnx</Link>
6671
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
6772
</Content>
6873
</ItemGroup>
6974

70-
<ItemGroup>
71-
<Folder Include="Dynamic\" />
72-
</ItemGroup>
75+
<ItemGroup>
76+
<Folder Include="Dynamic\" />
77+
</ItemGroup>
7378

7479
</Project>

eng/Versions.props

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -67,9 +67,13 @@
6767
<ParquetDotNetVersion>2.1.3</ParquetDotNetVersion>
6868
<PlotlyNETCSharpVersion>0.11.1</PlotlyNETCSharpVersion>
6969
<SharpZipLibVersion>1.4.2</SharpZipLibVersion>
70-
<TensorflowDotNETVersion>0.20.1</TensorflowDotNETVersion>
70+
<!-- TensorFlow.NET cannot be updated past 0.100.2 due to https://github.com/SciSharp/TensorFlow.NET/issues/1296,
71+
and regression https://github.com/SciSharp/TensorFlow.NET/commit/a7c9a75954d219cb606042fcbfbeb1b176781d7e introduced in 0.100.4 -->
72+
<TensorflowDotNETVersion>0.100.2</TensorflowDotNETVersion>
7173
<TensorFlowMajorVersion>2</TensorFlowMajorVersion>
72-
<TensorFlowVersion>2.3.1</TensorFlowVersion>
74+
<TensorFlowVersion>2.16.0</TensorFlowVersion>
75+
<TensorFlowWindowsGpuVersion>2.10.3</TensorFlowWindowsGpuVersion>
76+
<TensorFlowLinuxGpuVersion>2.11.1</TensorFlowLinuxGpuVersion>
7377
<TorchSharpPyBridgeVersion>1.4.1</TorchSharpPyBridgeVersion>
7478
<AutoGenVersion>0.2.3</AutoGenVersion>
7579
<SemanticKernelVersion>1.48.0</SemanticKernelVersion>

src/Microsoft.ML.TensorFlow/TensorTypeExtensions.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ public static void ToScalar<T>(this Tensor tensor, ref T dst) where T : unmanage
2525
return;
2626
}
2727

28-
if (typeof(T).as_dtype() != tensor.dtype)
28+
if (typeof(T).as_tf_dtype() != tensor.dtype)
2929
throw new NotSupportedException();
3030

3131
unsafe
@@ -37,7 +37,7 @@ public static void ToScalar<T>(this Tensor tensor, ref T dst) where T : unmanage
3737

3838
public static void CopyTo<T>(this Tensor tensor, Span<T> values) where T : unmanaged
3939
{
40-
if (typeof(T).as_dtype() != tensor.dtype)
40+
if (typeof(T).as_tf_dtype() != tensor.dtype)
4141
throw new NotSupportedException();
4242

4343
unsafe

src/Microsoft.ML.TensorFlow/TensorflowTransform.cs

Lines changed: 30 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,8 @@
1616
using Microsoft.ML.Runtime;
1717
using Microsoft.ML.TensorFlow;
1818
using Microsoft.ML.Transforms;
19-
using NumSharp;
2019
using Tensorflow;
20+
using Tensorflow.NumPy;
2121
using static Microsoft.ML.TensorFlow.TensorFlowUtils;
2222
using static Tensorflow.Binding;
2323
using Utils = Microsoft.ML.Internal.Utilities.Utils;
@@ -51,7 +51,7 @@ public sealed class TensorFlowTransformer : RowToRowTransformerBase, IDisposable
5151
internal readonly DataViewType[] OutputTypes;
5252
internal readonly TF_DataType[] TFOutputTypes;
5353
internal readonly TF_DataType[] TFInputTypes;
54-
internal readonly TensorShape[] TFInputShapes;
54+
internal readonly Shape[] TFInputShapes;
5555
internal readonly (Operation, int)[] TFInputOperations;
5656
internal readonly (Operation, int)[] TFOutputOperations;
5757
internal TF_Output[] TFInputNodes;
@@ -212,14 +212,14 @@ internal TensorFlowTransformer(IHostEnvironment env, TensorFlowEstimator.Options
212212
env.CheckValue(options, nameof(options));
213213
}
214214

215-
private static ITensorValueGetter CreateTensorValueGetter<T>(DataViewRow input, bool isVector, int colIndex, TensorShape tfShape)
215+
private static ITensorValueGetter CreateTensorValueGetter<T>(DataViewRow input, bool isVector, int colIndex, Shape tfShape)
216216
{
217217
if (isVector)
218218
return new TensorValueGetterVec<T>(input, colIndex, tfShape);
219219
return new TensorValueGetter<T>(input, colIndex, tfShape);
220220
}
221221

222-
private static ITensorValueGetter CreateTensorValueGetter(DataViewRow input, TF_DataType tfType, bool isVector, int colIndex, TensorShape tfShape)
222+
private static ITensorValueGetter CreateTensorValueGetter(DataViewRow input, TF_DataType tfType, bool isVector, int colIndex, Shape tfShape)
223223
{
224224
var type = Tf2MlNetType(tfType);
225225
return Utils.MarshalInvoke(CreateTensorValueGetter<int>, type.RawType, input, isVector, colIndex, tfShape);
@@ -230,7 +230,7 @@ private static ITensorValueGetter[] GetTensorValueGetters(
230230
int[] inputColIndices,
231231
bool[] isInputVector,
232232
TF_DataType[] tfInputTypes,
233-
TensorShape[] tfInputShapes)
233+
Shape[] tfInputShapes)
234234
{
235235
var srcTensorGetters = new ITensorValueGetter[inputColIndices.Length];
236236
for (int i = 0; i < inputColIndices.Length; i++)
@@ -331,10 +331,10 @@ private static (Operation, int) GetOperationFromName(string operation, Session s
331331
return (session.graph.OperationByName(operation), 0);
332332
}
333333

334-
internal static (TF_DataType[] tfInputTypes, TensorShape[] tfInputShapes, (Operation, int)[]) GetInputInfo(IHost host, Session session, string[] inputs, int batchSize = 1)
334+
internal static (TF_DataType[] tfInputTypes, Shape[] tfInputShapes, (Operation, int)[]) GetInputInfo(IHost host, Session session, string[] inputs, int batchSize = 1)
335335
{
336336
var tfInputTypes = new TF_DataType[inputs.Length];
337-
var tfInputShapes = new TensorShape[inputs.Length];
337+
var tfInputShapes = new Shape[inputs.Length];
338338
var tfInputOperations = new (Operation, int)[inputs.Length];
339339

340340
int index = 0;
@@ -351,15 +351,15 @@ internal static (TF_DataType[] tfInputTypes, TensorShape[] tfInputShapes, (Opera
351351
throw host.ExceptParam(nameof(session), $"Input type '{tfInputType}' of input column '{input}' is not supported in TensorFlow");
352352

353353
tfInputTypes[index] = tfInputType;
354-
tfInputShapes[index] = ((Tensor)inputTensor).TensorShape;
354+
tfInputShapes[index] = ((Tensor)inputTensor).shape;
355355
tfInputOperations[index] = (inputTensor, inputTensorIndex);
356356
index++;
357357
}
358358

359359
return (tfInputTypes, tfInputShapes, tfInputOperations);
360360
}
361361

362-
internal static TensorShape GetTensorShape(TF_Output output, Graph graph, Status status = null)
362+
internal static Shape GetTensorShape(TF_Output output, Graph graph, Status status = null)
363363
{
364364
if (graph == IntPtr.Zero)
365365
throw new ObjectDisposedException(nameof(graph));
@@ -370,12 +370,12 @@ internal static TensorShape GetTensorShape(TF_Output output, Graph graph, Status
370370
cstatus.Check();
371371

372372
if (n == -1)
373-
return new TensorShape(new int[0]);
373+
return new Shape(new int[0]);
374374

375375
var dims = new long[n];
376376
c_api.TF_GraphGetTensorShape(graph, output, dims, dims.Length, cstatus.Handle);
377377
cstatus.Check();
378-
return new TensorShape(dims.Select(x => (int)x).ToArray());
378+
return new Shape(dims.Select(x => (int)x).ToArray());
379379
}
380380

381381
internal static (TF_DataType[] tfOutputTypes, DataViewType[] outputTypes, (Operation, int)[]) GetOutputInfo(IHost host, Session session, string[] outputs, bool treatOutputAsBatched)
@@ -402,7 +402,7 @@ internal static (TF_DataType[] tfOutputTypes, DataViewType[] outputTypes, (Opera
402402
// i.e. the first dimension (if unknown) is assumed to be batch dimension.
403403
// If there are other dimension that are unknown the transformer will return a variable length vector.
404404
// This is the work around in absence of reshape transformer.
405-
var idims = shape.dims;
405+
var idims = shape.dims.Select(x => checked((int)x)).ToArray();
406406

407407
int[] dims = idims;
408408
if (treatOutputAsBatched)
@@ -517,7 +517,7 @@ public void Dispose()
517517

518518
if (Session != null && Session != IntPtr.Zero)
519519
{
520-
Session.close(); // invoked Dispose()
520+
Session.Dispose();
521521
}
522522
}
523523
finally
@@ -536,7 +536,7 @@ private sealed class Mapper : MapperBase
536536
private readonly TensorFlowTransformer _parent;
537537
private readonly int[] _inputColIndices;
538538
private readonly bool[] _isInputVector;
539-
private readonly TensorShape[] _fullySpecifiedShapes;
539+
private readonly Shape[] _fullySpecifiedShapes;
540540
private readonly ConcurrentBag<Runner> _runners;
541541

542542
public Mapper(TensorFlowTransformer parent, DataViewSchema inputSchema) :
@@ -546,7 +546,7 @@ public Mapper(TensorFlowTransformer parent, DataViewSchema inputSchema) :
546546
_parent = parent;
547547
_inputColIndices = new int[_parent.Inputs.Length];
548548
_isInputVector = new bool[_parent.Inputs.Length];
549-
_fullySpecifiedShapes = new TensorShape[_parent.Inputs.Length];
549+
_fullySpecifiedShapes = new Shape[_parent.Inputs.Length];
550550
for (int i = 0; i < _parent.Inputs.Length; i++)
551551
{
552552
if (!inputSchema.TryGetColumnIndex(_parent.Inputs[i], out _inputColIndices[i]))
@@ -570,19 +570,19 @@ public Mapper(TensorFlowTransformer parent, DataViewSchema inputSchema) :
570570
{
571571
vecType = (VectorDataViewType)type;
572572
var colTypeDims = vecType.Dimensions.Select(dim => (int)dim).ToArray();
573-
_fullySpecifiedShapes[i] = new TensorShape(colTypeDims);
573+
_fullySpecifiedShapes[i] = new Shape(colTypeDims);
574574
}
575575
else
576576
// for primitive type use default TensorShape
577-
_fullySpecifiedShapes[i] = new TensorShape();
577+
_fullySpecifiedShapes[i] = new Shape(Array.Empty<long>());
578578
}
579579
else
580580
{
581581
vecType = (VectorDataViewType)type;
582582
var colTypeDims = vecType.Dimensions.Select(dim => (int)dim).ToArray();
583583
// If the column is one dimension we make sure that the total size of the TF shape matches.
584584
// Compute the total size of the known dimensions of the shape.
585-
int valCount = 1;
585+
long valCount = 1;
586586
int numOfUnkDim = 0;
587587
foreach (var s in shape)
588588
{
@@ -592,7 +592,7 @@ public Mapper(TensorFlowTransformer parent, DataViewSchema inputSchema) :
592592
numOfUnkDim++;
593593
}
594594
// The column length should be divisible by this, so that the other dimensions can be integral.
595-
int typeValueCount = type.GetValueCount();
595+
long typeValueCount = type.GetValueCount();
596596
if (typeValueCount % valCount != 0)
597597
throw Contracts.Except($"Input shape mismatch: Input '{_parent.Inputs[i]}' has shape {originalShape.ToString()}, but input data is of length {typeValueCount}.");
598598

@@ -616,22 +616,22 @@ public Mapper(TensorFlowTransformer parent, DataViewSchema inputSchema) :
616616
throw Contracts.Except($"Input shape mismatch: Input '{_parent.Inputs[i]}' has shape {originalShape.ToString()}, but input data is of length {typeValueCount}.");
617617

618618
// Fill in the unknown dimensions.
619-
var l = new int[originalShapeNdim];
619+
var l = new long[originalShapeNdim];
620620
for (int ishape = 0; ishape < originalShapeNdim; ishape++)
621-
l[ishape] = originalShapeDims[ishape] == -1 ? (int)d : originalShapeDims[ishape];
622-
_fullySpecifiedShapes[i] = new TensorShape(l);
621+
l[ishape] = originalShapeDims[ishape] == -1 ? (long)d : originalShapeDims[ishape];
622+
_fullySpecifiedShapes[i] = new Shape(l);
623623
}
624624

625625
if (_parent._addBatchDimensionInput)
626626
{
627627
// ndim of default TensorShape is -1, make originDim to 0 in this case.
628628
// after addBatchDimension, input column will be changed: type -> type[]
629629
var originDim = _fullySpecifiedShapes[i].ndim < 0 ? 0 : _fullySpecifiedShapes[i].ndim;
630-
var l = new int[originDim + 1];
630+
var l = new long[originDim + 1];
631631
l[0] = 1;
632632
for (int ishape = 1; ishape < l.Length; ishape++)
633633
l[ishape] = _fullySpecifiedShapes[i].dims[ishape - 1];
634-
_fullySpecifiedShapes[i] = new TensorShape(l);
634+
_fullySpecifiedShapes[i] = new Shape(l);
635635
}
636636
}
637637

@@ -720,7 +720,7 @@ private Delegate MakeGetter<T>(DataViewRow input, int iinfo, ITensorValueGetter[
720720
UpdateCacheIfNeeded(input.Position, srcTensorGetters, activeOutputColNames, outputCache);
721721

722722
var tensor = outputCache.Outputs[_parent.Outputs[iinfo]];
723-
var tensorSize = tensor.TensorShape.dims.Where(x => x > 0).Aggregate((x, y) => x * y);
723+
var tensorSize = tensor.shape.dims.Where(x => x > 0).Aggregate((x, y) => x * y);
724724

725725
var editor = VBufferEditor.Create(ref dst, (int)tensorSize);
726726
FetchStringData(tensor, editor.Values);
@@ -735,7 +735,7 @@ private Delegate MakeGetter<T>(DataViewRow input, int iinfo, ITensorValueGetter[
735735
UpdateCacheIfNeeded(input.Position, srcTensorGetters, activeOutputColNames, outputCache);
736736

737737
var tensor = outputCache.Outputs[_parent.Outputs[iinfo]];
738-
var tensorSize = tensor.TensorShape.dims.Where(x => x > 0).Aggregate((x, y) => x * y);
738+
var tensorSize = tensor.shape.dims.Where(x => x > 0).Aggregate((x, y) => x * y);
739739

740740
var editor = VBufferEditor.Create(ref dst, (int)tensorSize);
741741

@@ -821,10 +821,10 @@ private class TensorValueGetter<T> : ITensorValueGetter
821821
{
822822
private readonly ValueGetter<T> _srcgetter;
823823
private readonly T[] _bufferedData;
824-
private readonly TensorShape _tfShape;
824+
private readonly Shape _tfShape;
825825
private int _position;
826826

827-
public TensorValueGetter(DataViewRow input, int colIndex, TensorShape tfShape)
827+
public TensorValueGetter(DataViewRow input, int colIndex, Shape tfShape)
828828
{
829829
_srcgetter = input.GetGetter<T>(input.Schema[colIndex]);
830830
_tfShape = tfShape;
@@ -864,15 +864,15 @@ public Tensor GetBufferedBatchTensor()
864864
private class TensorValueGetterVec<T> : ITensorValueGetter
865865
{
866866
private readonly ValueGetter<VBuffer<T>> _srcgetter;
867-
private readonly TensorShape _tfShape;
867+
private readonly Shape _tfShape;
868868
private VBuffer<T> _vBuffer;
869869
private T[] _denseData;
870870
private T[] _bufferedData;
871871
private int _position;
872872
private readonly long[] _dims;
873873
private readonly long _bufferedDataSize;
874874

875-
public TensorValueGetterVec(DataViewRow input, int colIndex, TensorShape tfShape)
875+
public TensorValueGetterVec(DataViewRow input, int colIndex, Shape tfShape)
876876
{
877877
_srcgetter = input.GetGetter<VBuffer<T>>(input.Schema[colIndex]);
878878
_tfShape = tfShape;

0 commit comments

Comments
 (0)