tensorflow 在指定CPU/GPU上运行方法

本文介绍了如何在TensorFlow中配置和使用GPU进行高效运算。包括理解设备标识符、默认的设备分配策略、如何手动指定设备、多GPU环境下的任务分配等关键概念。
部署运行你感兴趣的模型镜像

转自:http://wiki.jikexueyuan.com/project/tensorflow-zh/how_tos/using_gpu.html

使用 GPUs

支持的设备

在一套标准的系统上通常有多个计算设备. TensorFlow 支持 CPU 和 GPU 这两种设备. 我们用指定字符串 strings 来标识这些设备. 比如:

  • "/cpu:0": 机器中的 CPU
  • "/gpu:0": 机器中的 GPU, 如果你有一个的话.
  • "/gpu:1": 机器中的第二个 GPU, 以此类推...

如果一个 TensorFlow 的 operation 中兼有 CPU 和 GPU 的实现, 当这个算子被指派设备时, GPU 有优先权. 比如matmul中 CPU 和 GPU kernel 函数都存在. 那么在 cpu:0 和 gpu:0 中, matmul operation 会被指派给 gpu:0 .

记录设备指派情况

为了获取你的 operations 和 Tensor 被指派到哪个设备上运行, 用 log_device_placement 新建一个 session, 并设置为 True.

# 新建一个 graph.
a = tf.constant([1.0, 2.0, 3.0, 4.0, 5.0, 6.0], shape=[2, 3], name='a')
b = tf.constant([1.0, 2.0, 3.0, 4.0, 5.0, 6.0], shape=[3, 2], name='b')
c = tf.matmul(a, b)
# 新建session with log_device_placement并设置为True.
sess = tf.Session(config=tf.ConfigProto(log_device_placement=True))
# 运行这个 op.
print sess.run(c)

你应该能看见以下输出:

Device mapping:
/job:localhost/replica:0/task:0/gpu:0 -> device: 0, name: Tesla K40c, pci bus
id: 0000:05:00.0
b: /job:localhost/replica:0/task:0/gpu:0
a: /job:localhost/replica:0/task:0/gpu:0
MatMul: /job:localhost/replica:0/task:0/gpu:0
[[ 22.  28.]
 [ 49.  64.]]

手工指派设备

如果你不想使用系统来为 operation 指派设备, 而是手工指派设备, 你可以用 with tf.device 创建一个设备环境, 这个环境下的 operation 都统一运行在环境指定的设备上.

# 新建一个graph.
with tf.device('/cpu:0'):
  a = tf.constant([1.0, 2.0, 3.0, 4.0, 5.0, 6.0], shape=[2, 3], name='a')
  b = tf.constant([1.0, 2.0, 3.0, 4.0, 5.0, 6.0], shape=[3, 2], name='b')
c = tf.matmul(a, b)
# 新建session with log_device_placement并设置为True.
sess = tf.Session(config=tf.ConfigProto(log_device_placement=True))
# 运行这个op.
print sess.run(c)

你会发现现在 a 和 b 操作都被指派给了 cpu:0.

Device mapping:
/job:localhost/replica:0/task:0/gpu:0 -> device: 0, name: Tesla K40c, pci bus
id: 0000:05:00.0
b: /job:localhost/replica:0/task:0/cpu:0
a: /job:localhost/replica:0/task:0/cpu:0
MatMul: /job:localhost/replica:0/task:0/gpu:0
[[ 22.  28.]
 [ 49.  64.]]

在多GPU系统里使用单一GPU

如果你的系统里有多个 GPU, 那么 ID 最小的 GPU 会默认使用. 如果你想用别的 GPU, 可以用下面的方法显式的声明你的偏好:

# 新建一个 graph.
with tf.device('/gpu:2'):
  a = tf.constant([1.0, 2.0, 3.0, 4.0, 5.0, 6.0], shape=[2, 3], name='a')
  b = tf.constant([1.0, 2.0, 3.0, 4.0, 5.0, 6.0], shape=[3, 2], name='b')
  c = tf.matmul(a, b)
# 新建 session with log_device_placement 并设置为 True.
sess = tf.Session(config=tf.ConfigProto(log_device_placement=True))
# 运行这个 op.
print sess.run(c)

如果你指定的设备不存在, 你会收到 InvalidArgumentError 错误提示:

InvalidArgumentError: Invalid argument: Cannot assign a device to node 'b':
Could not satisfy explicit device specification '/gpu:2'
   [[Node: b = Const[dtype=DT_FLOAT, value=Tensor<type: float shape: [3,2]
   values: 1 2 3...>, _device="/gpu:2"]()]]

为了避免出现你指定的设备不存在这种情况, 你可以在创建的 session 里把参数 allow_soft_placement 设置为 True, 这样 tensorFlow 会自动选择一个存在并且支持的设备来运行 operation.

# 新建一个 graph.
with tf.device('/gpu:2'):
  a = tf.constant([1.0, 2.0, 3.0, 4.0, 5.0, 6.0], shape=[2, 3], name='a')
  b = tf.constant([1.0, 2.0, 3.0, 4.0, 5.0, 6.0], shape=[3, 2], name='b')
  c = tf.matmul(a, b)
# 新建 session with log_device_placement 并设置为 True.
sess = tf.Session(config=tf.ConfigProto(
      allow_soft_placement=True, log_device_placement=True))
# 运行这个 op.
print sess.run(c)

使用多个 GPU

如果你想让 TensorFlow 在多个 GPU 上运行, 你可以建立 multi-tower 结构, 在这个结构 里每个 tower 分别被指配给不同的 GPU 运行. 比如:

# 新建一个 graph.
c = []
for d in ['/gpu:2', '/gpu:3']:
  with tf.device(d):
    a = tf.constant([1.0, 2.0, 3.0, 4.0, 5.0, 6.0], shape=[2, 3])
    b = tf.constant([1.0, 2.0, 3.0, 4.0, 5.0, 6.0], shape=[3, 2])
    c.append(tf.matmul(a, b))
with tf.device('/cpu:0'):
  sum = tf.add_n(c)
# 新建session with log_device_placement并设置为True.
sess = tf.Session(config=tf.ConfigProto(log_device_placement=True))
# 运行这个op.
print sess.run(sum)

你会看到如下输出:

Device mapping:
/job:localhost/replica:0/task:0/gpu:0 -> device: 0, name: Tesla K20m, pci bus
id: 0000:02:00.0
/job:localhost/replica:0/task:0/gpu:1 -> device: 1, name: Tesla K20m, pci bus
id: 0000:03:00.0
/job:localhost/replica:0/task:0/gpu:2 -> device: 2, name: Tesla K20m, pci bus
id: 0000:83:00.0
/job:localhost/replica:0/task:0/gpu:3 -> device: 3, name: Tesla K20m, pci bus
id: 0000:84:00.0
Const_3: /job:localhost/replica:0/task:0/gpu:3
Const_2: /job:localhost/replica:0/task:0/gpu:3
MatMul_1: /job:localhost/replica:0/task:0/gpu:3
Const_1: /job:localhost/replica:0/task:0/gpu:2
Const: /job:localhost/replica:0/task:0/gpu:2
MatMul: /job:localhost/replica:0/task:0/gpu:2
AddN: /job:localhost/replica:0/task:0/cpu:0
[[  44.   56.]
 [  98.  128.]]

cifar10 tutorial 这个例子很好的演示了怎样用GPU集群训练.


您可能感兴趣的与本文相关的镜像

TensorFlow-v2.15

TensorFlow-v2.15

TensorFlow

TensorFlow 是由Google Brain 团队开发的开源机器学习框架,广泛应用于深度学习研究和生产环境。 它提供了一个灵活的平台,用于构建和训练各种机器学习模型

<think> 我们正在使用TensorFlow.NET 0.150.0版本,在这个版本中,加载模型的方法可能已经有所改变。根据版本更新日志,0.15.0版本开始,`load_model`方法已经支持`custom_objects`参数(注意:在C#中,参数名使用下划线命名法,即`custom_objects`,而不是驼峰命名法`customObjects`)。但是,用户报告的错误是CS1739,即没有名为`customObjects`的参数,这很可能是由于参数名写错导致的。 在TensorFlow.NET 0.150.0中,`load_model`方法的正确参数名是`custom_objects`(带下划线)。因此,我们需要将代码中的参数名从`customObjects`改为`custom_objects`。 此外,我们还需要确保自定义层(如`BayesianDense`)已经正确定义,并且被包含在`custom_objects`字典中。 下面是在TensorFlow.NET 0.150.0中加载模型的正确步骤: 1. 定义自定义层(与训练时保存的模型中的自定义层完全一致)。 2. 创建一个字典,将自定义层的名称(字符串)映射到对应的C#类型。 3. 使用`tf.keras.models.load_model`方法加载模型,并传入`custom_objects`参数。 代码示例: ```csharp using System; using System.Collections.Generic; using Tensorflow; using Tensorflow.Keras; using Tensorflow.Keras.Models; using NumSharp; namespace KerasNETPrediction { // 自定义层定义(必须与训练时保存的模型中的自定义层结构一致) [Serializable] public class BayesianDense : Tensorflow.Keras.Layers.Layer { private int units; public BayesianDense(int units) { this.units = units; } // 需要无参构造函数用于序列化 public BayesianDense() : this(0) { } protected override void build(Shape input_shape) { // 构建权重等 base.build(input_shape); } public override void call(Tensor inputs, Tensor training = null) { // 实现自定义层的前向传播 // 注意:这里只是示例,需要根据实际实现 base.call(inputs, training); } // 必须重写Config属性,返回自定义层的配置参数 public override IDictionary<string, object> Config => new Dictionary<string, object> { { "units", units } }; } class Program { static void Main(string[] args) { // 设置自定义对象的字典 var custom_objects = new Dictionary<string, Type> { { "BayesianDense", typeof(BayesianDense) } }; // 加载模型 var model = tf.keras.models.load_model(@"D:\models\bayesian_model.h5", custom_objects: custom_objects); // 使用模型进行预测... // 示例:创建一个输入数据 var input = np.array(new float[,] { { 1.0f, 2.0f, 3.0f } }); var result = model.predict(input); // 输出结果 Console.WriteLine(result.ToString()); } } } ``` 注意: - 在自定义层中,必须包含无参数的构造函数,因为反序列化时会使用它。 - 必须使用`[Serializable]`特性标记自定义层类。 - 重写`Config`属性,返回创建该层时使用的配置参数(例如,`units`)。这样在加载模型时,才能正确重建该层。 如果按照以上步骤仍然遇到问题,请检查以下事项: 1. 确保自定义层类的命名空间与训练模型时使用的完全一致。如果训练模型时使用的自定义层在一个特定的命名空间中,那么在加载模型时,自定义层的定义也必须在相同的命名空间中,或者通过字典中的字符串键完全限定(例如`"MyNamespace.BayesianDense"`)。 2. 确保自定义层的实现与训练时完全一致,包括成员变量和方法。 如果问题仍然存在,可能需要检查TensorFlow.NET的版本是否完全匹配,或者尝试更新到最新版本。 §§相关问题§§ 1. 如何在TensorFlow.NET中定义自定义层? 2. TensorFlow.NET中保存和加载模型的最佳实践是什么? 3. 如何解决TensorFlow.NET中的版本兼容性问题? 4. 在TensorFlow.NET中,如何将自定义层从Python转换到C#? </think># TensorFlow.NET 0.150.0 模型加载指南 在 TensorFlow.NET 0.150.0 环境中加载模型时,需要注意 API 的特定用法。以下是针对您指定环境(NumSharp 0.30.0/TensorFlow.NET 0.150.0)的完整解决方案。 ## 完整代码实现 ```csharp using System; using System.Collections.Generic; using Tensorflow; using Tensorflow.Keras; using Tensorflow.Keras.Models; using NumSharp; // 1. 自定义层定义(必须与训练时一致) [Serializable] public class BayesianDense : Tensorflow.Keras.Layers.Layer { private int _units; public BayesianDense(int units) : base() { _units = units; } // 必须有无参构造函数 public BayesianDense() : this(0) {} protected override void build(Shape input_shape) { // 添加权重变量 add_weight("kernel", (input_shape[-1], _units), initializer: tf.keras.initializers.glorot_normal()); base.build(input_shape); } protected override Tensors call(Tensors inputs, Tensor state = null, bool? training = null) { // 实际计算逻辑 return inputs; } // 必须实现Config属性 public override IDictionary<string, object> Config => new Dictionary<string, object> { { "units", _units } }; } class ModelLoader { static void Main(string[] args) { // 设置TensorFlow后端 tf.enable_eager_execution(); tf.Context.ensure_initialized(); Console.WriteLine($"TensorFlow版本: {tf.VERSION}"); Console.WriteLine($"TensorFlow.NET版本: {tf.__version__}"); // 2. 注册自定义对象 var custom_objects = new Dictionary<string, Type> { { "BayesianDense", typeof(BayesianDense) }, // 添加其他自定义类... }; try { // 3. 加载模型(注意参数名) IModel model = tf.keras.models.load_model( @"D:\models\bayesian_model.h5", custom_objects: custom_objects ); Console.WriteLine("✅ 模型加载成功"); Console.WriteLine(model.summary()); // 4. 验证自定义层 foreach (var layer in model.Layers) { if (layer is BayesianDense bayesianLayer) { Console.WriteLine($"检测到BayesianDense层,单元数: {bayesianLayer.Config["units"]}"); } } // 5. 准备输入数据 var input = np.array(new float[,] { { 0.1f, 0.2f, 0.3f } }); // 6. 执行预测 Tensor predictions = model.predict(input); var results = predictions.numpy().ToArray<float>(); Console.WriteLine($"预测结果: {string.Join(", ", results)}"); } catch (Exception ex) { Console.WriteLine($"❌ 加载失败: {ex.Message}"); if (ex.Message.Contains("Unknown layer")) { Console.WriteLine("解决方案:"); Console.WriteLine("1. 检查custom_objects字典是否包含所有自定义类"); Console.WriteLine("2. 确保自定义层名称与训练时完全一致"); } } } } ``` ## 关键配置说明 ### 1. 环境依赖配置 | 组件 | 版本 | 安装命令 | |------|------|----------| | TensorFlow.NET | 0.150.0 | `Install-Package TensorFlow.NET -Version 0.150.0` | | TensorFlow.Keras | 0.15.0 | `Install-Package TensorFlow.Keras -Version 0.15.0` | | NumSharp | 0.30.0 | `Install-Package NumSharp -Version 0.30.0` | | SciSharp.TensorFlow.Redist | 2.16.0 (CPU) | `Install-Package SciSharp.TensorFlow.Redist -Version 2.16.0` | | SciSharp.TensorFlow.Redist-Windows-GPU | 2.10.0 (GPU) | `Install-Package SciSharp.TensorFlow.Redist-Windows-GPU -Version 2.10.0` | ### 2. 自定义层实现要点 在 TensorFlow.NET 0.150.0 中,自定义层需要满足以下要求: ```csharp [Serializable] public class CustomLayer : Tensorflow.Keras.Layers.Layer { // 必须包含无参构造函数 public CustomLayer() : base() {} // 主构造函数 public CustomLayer(int units) : base() { // 初始化逻辑 } // 必须实现build方法 protected override void build(Shape input_shape) { // 创建权重 add_weight("weight", (input_shape[-1], 64)); base.build(input_shape); } // 必须实现call方法 protected override Tensors call(Tensors inputs, Tensor state = null, bool? training = null) { // 层逻辑 return inputs; } // 必须实现Config属性 public override IDictionary<string, object> Config => new Dictionary<string, object> { { "units", 64 } }; } ``` ### 3. 模型加载参数说明 | 参数 | 类型 | 必需 | 说明 | |------|------|------|------| | `filepath` | string | 是 | 模型文件路径(.h5 或 SavedModel 目录) | | `custom_objects` | `Dictionary<string, Type>` | 可选 | 自定义层映射 | | `compile` | bool | 可选 | 是否编译模型(默认 true) | ## 常见问题解决方案 ### 问题1: Unknown layer: BayesianDense **解决方案**: 1. 检查 `custom_objects` 字典键名是否与层名完全匹配 2. 确保自定义层包含在模型加载代码的同一程序集中 3. 验证自定义层实现了 `Config` 属性 ### 问题2: ValueError: No model found in config file **解决方案**: ```csharp // 尝试加载为 SavedModel 格式 IModel model = tf.keras.models.load_model( @"D:\models\saved_model_directory", custom_objects: custom_objects ); ``` ### 问题3: 版本不兼容错误 **降级兼容方案**: ```csharp // 对于旧版本TensorFlow.NET var model = new Sequential(); model.load_weights(@"D:\models\bayesian_model_weights.h5"); ``` ## 模型保存最佳实践 ```csharp // 保存完整模型(包含结构和权重) model.save(@"D:\models\full_model.h5", save_format: "h5"); // 仅保存权重 model.save_weights(@"D:\models\model_weights.h5"); // 保存为SavedModel格式(跨平台兼容) model.save(@"D:\models\saved_model", save_format: "tf"); ``` ## 性能优化技巧 ```csharp // 启用GPU加速(如果可用) if (tf.config.list_physical_devices('GPU').Count > 0) { tf.config.experimental.set_memory_growth( tf.config.list_physical_devices('GPU')[0], true); } // 批量预测提高效率 var batchInput = np.array(new float[100, 10]); // 100个样本 model.predict(batchInput, batch_size: 32); ``` > **注意**:TensorFlow.NET 0.150.0 要求 .NET Standard 2.0 或更高版本,建议使用 .NET 6+ 运行时环境以获得最佳性能[^1]。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值