.NET4.7.2+VS2017下Tensorflow.Binding类型初始化异常求解
环境说明
- .NET Framework 4.7.2
- Visual Studio 2017
- Tensorflow.NET v0.150.0(Haiping Cheng开发)
自定义TfMatrix类源码
using System; using System.Linq; using Tensorflow; using static Tensorflow.Binding; namespace SimulationLib { public class TfMatrix : IEquatable<TfMatrix> { private Tensor _matrix; public TfMatrix(float[,] values) { if (values == null || values.GetLength(0) == 0 || values.GetLength(1) == 0) throw new ArgumentException("Values array must not be null or empty."); _matrix = tf.constant(values); } public TfMatrix(int rows, int cols) { if (rows <= 0 || cols <= 0) throw new ArgumentException("Number of rows and columns must be positive."); _matrix = tf.zeros(new int[] { rows, cols }, tf.float32); } public TfMatrix(TfMatrix m) { if (m == null) throw new ArgumentNullException(nameof(m)); _matrix = tf.identity(m._matrix); // Using identity instead of Clone } public TfMatrix(Tensor tensor) { if (tensor == null) throw new ArgumentNullException(nameof(tensor)); _matrix = tensor; // Directly assign the provided tensor to the matrix field } // Indexer for accessing and modifying elements public float this[int row, int col] { get { var slice = tf.strided_slice(_matrix, new int[] { row, col }, new int[] { row + 1, col + 1 }); return slice.numpy().ToArray<float>().First(); } set { // Convert the matrix to a mutable tensor (this will create a copy) var updatedMatrix = _matrix.numpy(); // Update the specific element updatedMatrix[row, col] = value; // Convert the updated array back to a tensor _matrix = tf.constant(updatedMatrix); } } public int Rows => (int)_matrix.shape[0]; public int Columns => (int)_matrix.shape[1]; } }
测试代码
using System; using Microsoft.VisualStudio.TestTools.UnitTesting; using Tensorflow; using static Tensorflow.Binding; namespace SimulationLib.Tests { [TestClass] public class TfMatrixTests { [TestMethod] public void TestConstructorWith2DArray() { float[,] values = new float[,] { { 1, 2 }, { 3, 4 } }; TfMatrix matrix = new TfMatrix(values); Assert.AreEqual(2, matrix.Rows); Assert.AreEqual(2, matrix.Columns); Assert.AreEqual(1, matrix[0, 0]); Assert.AreEqual(4, matrix[1, 1]); } } }
报错信息
测试名称: TestConstructorWith2DArray
测试完整名称: SimulationLib.Tests.TfMatrixTests.TestConstructorWith2DArray
测试来源: C:\git\Simulation\Simulation\unit_test_3d_for_TfMatrix\UnitTest1.cs : line 12
测试结果: 失败
测试时长: 0:00:01.2855111调用堆栈跟踪:
at System.Reflection.RuntimeModule.GetTypes(RuntimeModule module)
at System.Reflection.RuntimeModule.GetTypes()
at System.Reflection.Assembly.GetTypes()
at Tensorflow.ops.RegisterFromAssembly()
at Tensorflow.tensorflow.InitGradientEnvironment()
at Tensorflow.tensorflow..ctor()
at Tensorflow.Binding..cctor()
--- 内部异常堆栈跟踪结束 ---
at Tensorflow.Binding.get_tf()
at SimulationLib.TfMatrix..ctor(Single[,] values) in C:\git\Simulation\Simulation\PolymerSimLib\Primitives\TfMatrix.cs:line 17
at SimulationLib.Tests.TfMatrixTests.TestConstructorWith2DArray() in C:\git\Simulation\Simulation\unit_test_3d_for_TfMatrix\UnitTest1.cs:line 15结果信息:
测试方法SimulationLib.Tests.TfMatrixTests.TestConstructorWith2DArray引发异常:
System.TypeInitializationException: The type initializer for 'Tensorflow.Binding' threw an exception.
System.Reflection.ReflectionTypeLoadException: Unable to load one or more of the requested types. Retrieve the LoaderExceptions property for more information.
解决方法
1. 检查并修复NuGet依赖
- 确保Tensorflow.NET v0.150.0及其所有依赖包(如
Tensorflow.Keras、Google.Protobuf、System.Memory等)都已正确安装,版本完全匹配。 - 清理NuGet缓存后重新安装:打开VS2017的工具→NuGet包管理器→程序包管理器设置,点击清除所有NuGet缓存,然后重新安装Tensorflow.NET v0.150.0。
2. 添加程序集绑定重定向
在项目的App.config中添加绑定重定向,解决版本冲突问题:
<runtime> <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1"> <dependentAssembly> <assemblyIdentity name="Google.Protobuf" publicKeyToken="a7d26565bac4d604" culture="neutral" /> <bindingRedirect oldVersion="0.0.0.0-3.19.0.0" newVersion="3.19.0.0" /> </dependentAssembly> <dependentAssembly> <assemblyIdentity name="System.Memory" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" /> <bindingRedirect oldVersion="0.0.0.0-4.0.1.1" newVersion="4.0.1.1" /> </dependentAssembly> <!-- 根据实际LoaderExceptions添加其他程序集的绑定重定向 --> </assemblyBinding> </runtime>
3. 排查具体加载失败的程序集
修改测试代码,捕获并输出LoaderExceptions的详细信息,明确问题根源:
[TestMethod] public void TestConstructorWith2DArray() { try { float[,] values = new float[,] { { 1, 2 }, { 3, 4 } }; TfMatrix matrix = new TfMatrix(values); Assert.AreEqual(2, matrix.Rows); Assert.AreEqual(2, matrix.Columns); Assert.AreEqual(1, matrix[0, 0]); Assert.AreEqual(4, matrix[1, 1]); } catch (TypeInitializationException ex) { if (ex.InnerException is ReflectionTypeLoadException loadEx) { foreach (var loaderEx in loadEx.LoaderExceptions) { Console.WriteLine("加载异常:"); Console.WriteLine(loaderEx.Message); Console.WriteLine(loaderEx.StackTrace); Console.WriteLine("---"); } } throw; } }
运行测试后查看输出,根据提示安装缺失的程序集或调整版本。
4. 验证Tensorflow原生库兼容性
- 将项目平台目标设置为x64:右键项目→属性→生成→平台目标,选择
x64(Tensorflow.NET v0.150.0对x86支持有限)。 - 安装对应版本的Tensorflow原生库:通过NuGet安装
Tensorflow.Runtime.Windowsv0.150.0,确保原生库与Tensorflow.NET版本匹配。
5. 调整项目设置
- 确认项目语言版本为C# 7.0及以上:右键项目→属性→生成→高级→语言版本,选择
C# 7.0。 - 关闭"仅我的代码":打开调试→选项→调试→常规,取消勾选"启用仅我的代码",以便查看更完整的异常详情。
内容的提问来源于stack exchange,提问作者user366312

