
教程深度学习机器学习【免费下载链接】eat_tensorflow2_in_30_daysTensorflow2.0 is delicious, just eat it! 项目地址https://gitcode.com/gh_mirrors/ea/eat_tensorflow2_in_30_days点击查看免费下载本文是《30天吃掉那只TensorFlow2》高阶API章节六、TensorFlow的高阶API的第 6-4 节配套实战指南聚焦使用多GPU训练模型这一高频需求。当单卡显存不足、或希望成倍缩短参数迭代时间时TensorFlow 2 提供的tf.distribute.MirroredStrategy是上手门槛最低的方案——在原有内置fit训练流程上仅需增加两行代码即可将训练扩展到多张 GPU 上。读完本文你将掌握MirroredStrategy 同步数据并行的完整工作原理、在 Colab 上用单张物理 GPU 模拟多逻辑 GPU 的方法、以及一套可直接复制运行的 Reuters 文本分类多卡训练完整代码。本文全部代码基于本书 README.md 中说明的TensorFlow 2.1环境编写并在 Colab 上验证通过配套英文版见 english/Chapter6-4.md。一为什么要用多GPU训练训练耗时从哪来深度学习的训练过程常常非常耗时耗时主要来自两部分数据准备与参数迭代详见 6-3,使用单GPU训练模型当数据准备过程是主要瓶颈时通常用更多进程来准备数据如tf.data的并行读取与预取当参数迭代过程成为主要瓶颈时常规手段是使用GPU或 Google 的TPU进行加速。多 GPU 训练正是参数迭代维度的进一步加速把一个大批次的数据切分到 N 张卡上并行计算梯度再汇总更新参数从而以接近线性的速度提升训练吞吐。在 TensorFlow 2 中如果只是单 GPU 训练通常无需修改任何代码——存在可用 GPU 时 TensorFlow 会自动优先使用 GPU 创建张量和执行计算多使用者共享服务器时可通过tf.config.experimental.set_memory_growth与set_visible_devices控制显存与设备编号详见 6-3,使用单GPU训练模型。而多 GPU 训练则需要显式引入分布式策略。二MirroredStrategy 过程简介同步数据并行的六个步骤tf.distribute.MirroredStrategy镜像策略是 TensorFlow 2 内置的、最易用的单机多卡分布式训练策略。所谓镜像是指在每个计算设备上都保存一份完整的模型副本镜像变量训练时按数据并行方式协同工作。其完整过程如下复制模型训练开始前该策略在所有 N 个计算设备上均各复制一份完整的模型切分批次每次训练传入一个批次的数据时将数据分成 N 份分别传入 N 个计算设备即数据并行本地计算梯度N 个计算设备使用本地变量镜像变量分别计算自己所获得的那部分数据的梯度All-reduce 梯度汇总使用分布式计算的 All-reduce 操作在计算设备间高效交换梯度数据并进行求和使得最终每个设备都拥有了所有设备的梯度之和更新镜像变量使用梯度求和的结果更新本地变量镜像变量同步进入下一轮当所有设备均更新完本地变量后才进行下一轮训练——即该并行策略是同步的。可以这样理解N 张卡各算各的梯度、再互相通报求和每张卡最终拿到的都是全局一致的梯度因此各设备上的模型参数始终保持一致训练结果与单卡在数学上等价仅批大小被放大 N 倍这也是它被称为镜像的原因。从源码实现角度看策略的复制、切分、梯度聚合分别由tf.distribute.Strategy的模型副本机制、数据集experimental_distribute_dataset切分与跨设备梯度规约All-reduce机制共同支撑MirroredStrategy默认使用 NVIDIA NCCL 作为 All-reduce 通信后端吞吐性能出色当 NCCL 不可用时会自动回退到归约到单一设备再广播的方式下面实战日志中可见到这一回退提示。三环境准备Colab 开启 GPU 与逻辑GPU模拟本书多 GPU 范例设计为在Colab 笔记本上运行原文档明确说明以下代码只能在 Colab 上才能正确执行。开启方式在 Colab 笔记本中通过修改 - 笔记本设置 - 硬件加速器中选择 GPU。Colab 免费版通常只提供一张 GPU。为了演示多 GPU 训练流程范例利用 TensorFlow 的虚拟设备Virtual Device机制把 1 张物理 GPU 切分成两个各 1024MB 显存的逻辑 GPU从而在一台机器上模拟出双卡环境%tensorflow_version 2.x import tensorflow as tf print(tf.__version__) from tensorflow.keras import *# 此处在colab上使用1个GPU模拟出两个逻辑GPU进行多GPU训练 gpus tf.config.experimental.list_physical_devices(GPU) if gpus: # 设置两个逻辑GPU模拟多GPU训练 try: tf.config.experimental.set_virtual_device_configuration(gpus[0], [tf.config.experimental.VirtualDeviceConfiguration(memory_limit1024), tf.config.experimental.VirtualDeviceConfiguration(memory_limit1024)]) logical_gpus tf.config.experimental.list_logical_devices(GPU) print(len(gpus), Physical GPU,, len(logical_gpus), Logical GPUs) except RuntimeError as e: print(e)关键 API 说明tf.config.experimental.list_physical_devices(GPU)列出所有物理 GPU 设备tf.config.experimental.VirtualDeviceConfiguration(memory_limit1024)声明一个显存上限为 1024MB 的逻辑设备配置传入列表即为每个逻辑设备分配独立显存tf.config.experimental.set_virtual_device_configuration(gpus[0], [...])将第一张物理 GPU 按配置切分成多个虚拟设备tf.config.experimental.list_logical_devices(GPU)列出切分后的逻辑 GPU 数量正常情况下输出1 Physical GPU, 2 Logical GPUs若虚拟设备已被创建如重复运行单元格会抛出RuntimeError代码中用try/except捕获并打印提示。如果你在本地服务器上确实拥有多张物理 GPU则无需这段模拟代码MirroredStrategy()会自动探测并使用全部可见 GPU多使用者共享时可先参考 6-3,使用单GPU训练模型 中的set_visible_devices指定参与训练的卡。四完整实战Reuters 文本分类多GPU训练整个实战沿用本书统一的数据准备 - 定义模型 - 训练模型三段式流程与 6-2,训练模型的3种方法、6-3,使用单GPU训练模型 使用同一套 Reuters 新闻文本分类任务便于横向对比单卡/多卡/TPU 的训练效果。1准备数据MAX_LEN 300 BATCH_SIZE 32 (x_train,y_train),(x_test,y_test) datasets.reuters.load_data() x_train preprocessing.sequence.pad_sequences(x_train,maxlenMAX_LEN) x_test preprocessing.sequence.pad_sequences(x_test,maxlenMAX_LEN) MAX_WORDS x_train.max()1 CAT_NUM y_train.max()1 ds_train tf.data.Dataset.from_tensor_slices((x_train,y_train)) \ .shuffle(buffer_size 1000).batch(BATCH_SIZE) \ .prefetch(tf.data.experimental.AUTOTUNE).cache() ds_test tf.data.Dataset.from_tensor_slices((x_test,y_test)) \ .shuffle(buffer_size 1000).batch(BATCH_SIZE) \ .prefetch(tf.data.experimental.AUTOTUNE).cache()要点说明datasets.reuters.load_data()加载路透社新闻文本数据集每条样本为已编码的词索引序列preprocessing.sequence.pad_sequences(..., maxlenMAX_LEN)将序列统一填充/截断到 300 长度MAX_WORDS x_train.max()1为词汇表大小CAT_NUM y_train.max()1为分类类别数46 类数据管道按shuffle - batch - prefetch - cache顺序构建buffer_size1000打乱、BATCH_SIZE32分批、prefetch(tf.data.experimental.AUTOTUNE)让数据加载与计算流水线重叠、cache()将数据集缓存到内存以加速后续 epoch注意多 GPU 训练时每个设备的实际批大小为BATCH_SIZE / NN 为设备数这是与单卡唯一在数据流上的差异策略内部会自动完成切分无需手写。2定义模型tf.keras.backend.clear_session() def create_model(): model models.Sequential() model.add(layers.Embedding(MAX_WORDS,7,input_lengthMAX_LEN)) model.add(layers.Conv1D(filters 64,kernel_size 5,activation relu)) model.add(layers.MaxPool1D(2)) model.add(layers.Conv1D(filters 32,kernel_size 3,activation relu)) model.add(layers.MaxPool1D(2)) model.add(layers.Flatten()) model.add(layers.Dense(CAT_NUM,activation softmax)) return(model) def compile_model(model): model.compile(optimizeroptimizers.Nadam(), losslosses.SparseCategoricalCrossentropy(from_logitsTrue), metrics[metrics.SparseCategoricalAccuracy(),metrics.SparseTopKCategoricalAccuracy(5)]) return(model)要点说明模型为经典的词嵌入 一维卷积 全连接文本分类结构Embedding(MAX_WORDS, 7, input_lengthMAX_LEN)把 300 长度的词序列映射为 7 维向量随后两层Conv1DMaxPool1D提取局部 n-gram 特征Flatten后接 46 类的Dense softmax输出compile阶段使用optimizers.Nadam()优化器、losses.SparseCategoricalCrossentropy(from_logitsTrue)稀疏交叉熵损失以及SparseCategoricalAccuracy与SparseTopKCategoricalAccuracy(5)两个评估指标create_model与compile_model被封装成独立函数是为了方便在strategy.scope()作用域内统一创建与编译。3训练模型关键的两行代码# 增加以下两行代码 strategy tf.distribute.MirroredStrategy() with strategy.scope(): model create_model() model.summary() model compile_model(model) history model.fit(ds_train,validation_data ds_test,epochs 10)这就是原文档所说的推荐使用内置 fit 方法较为方便仅需添加 2 行代码strategy tf.distribute.MirroredStrategy()创建镜像策略对象此时策略会探测当前机器上的全部可见 GPU示例环境中即上一步切分出的两个逻辑 GPUwith strategy.scope():将模型的创建与编译放入策略作用域。这是使用任何tf.distribute策略时的硬性要求——只有在 scope 内创建的变量才会被自动转化为镜像变量每个设备一份副本并保持同步模型定义在 scope 之外将无法被策略托管。之后直接调用model.fit(ds_train, validation_datads_test, epochs10)即可内置 fit 方法会在内部自动完成批次切分到各设备 - 各设备前向反向 - 梯度 All-reduce 聚合 - 同步更新镜像变量的全流程训练逻辑本身不需要任何改动。这也是多 GPU 训练推荐使用内置 fit 方法的原因fit对分布式策略做了完整封装而自定义训练循环若要支持多卡则需要自行处理数据切分与梯度聚合复杂度明显更高。五训练过程日志解读启动训练后终端会输出策略初始化与训练进度信息其中包含几个值得关注的信号WARNING:tensorflow:NCCL is not supported when using virtual GPUs, fallingback to reduction to one device INFO:tensorflow:Using MirroredStrategy with devices (/job:localhost/replica:0/task:0/device:GPU:0, /job:localhost/replica:0/task:0/device:GPU:1)第一条 WARNING 说明在虚拟 GPU上 NCCL 通信后端不可用因此回退为归约到单一设备再广播的梯度聚合方式——这是本例为演示多卡而使用虚拟设备导致的正常现象在真实多张物理 GPU 上会默认使用 NCCL性能更高第二条 INFO 显示策略成功接管了两台设备GPU:0与GPU:1即上一步创建的两个逻辑 GPU训练过程中大量Reduce to ... then broadcast to ...的 INFO 日志正是第二节所述梯度 All-reduce 汇总后广播的底层执行记录观察可见梯度先在 GPU:0 上完成归约再广播回两个 GPU另有一部分变量归约发生在 CPU 上模型结构日志Model: sequential显示该模型共332,856 个可训练参数其中 Embedding 层占 216,874 个参数Train for 281 steps, validate for 71 steps训练集按 32 的批大小共 281 步、验证集 71 步。完整训练输出10 个 epoch如下WARNING:tensorflow:NCCL is not supported when using virtual GPUs, fallingback to reduction to one device INFO:tensorflow:Using MirroredStrategy with devices (/job:localhost/replica:0/task:0/device:GPU:0, /job:localhost/replica:0/task:0/device:GPU:1) Model: sequential _________________________________________________________________ Layer (type) Output Shape Param # embedding (Embedding) (None, 300, 7) 216874 _________________________________________________________________ conv1d (Conv1D) (None, 296, 64) 2304 _________________________________________________________________ max_pooling1d (MaxPooling1D) (None, 148, 64) 0 _________________________________________________________________ conv1d_1 (Conv1D) (None, 146, 32) 6176 _________________________________________________________________ max_pooling1d_1 (MaxPooling1 (None, 73, 32) 0 _________________________________________________________________ flatten (Flatten) (None, 2336) 0 _________________________________________________________________ dense (Dense) (None, 46) 107502 Total params: 332,856 Trainable params: 332,856 Non-trainable params: 0 _________________________________________________________________ INFO:tensorflow:Reduce to /job:localhost/replica:0/task:0/device:CPU:0 then broadcast to (/job:localhost/replica:0/task:0/device:CPU:0,). INFO:tensorflow:Reduce to /job:localhost/replica:0/task:0/device:CPU:0 then broadcast to (/job:localhost/replica:0/task:0/device:CPU:0,). INFO:tensorflow:Reduce to /job:localhost/replica:0/task:0/device:CPU:0 then broadcast to (/job:localhost/replica:0/task:0/device:CPU:0,). INFO:tensorflow:Reduce to /job:localhost/replica:0/task:0/device:CPU:0 then broadcast to (/job:localhost/replica:0/task:0/device:CPU:0,). Train for 281 steps, validate for 71 steps Epoch 1/10 INFO:tensorflow:Reduce to /job:localhost/replica:0/task:0/device:GPU:0 then broadcast to (/job:localhost/replica:0/task:0/device:GPU:0, /job:localhost/replica:0/task:0/device:GPU:1). INFO:tensorflow:Reduce to /job:localhost/replica:0/task:0/device:GPU:0 then broadcast to (/job:localhost/replica:0/task:0/device:GPU:0, /job:localhost/replica:0/task:0/device:GPU:1). INFO:tensorflow:Reduce to /job:localhost/replica:0/task:0/device:GPU:0 then broadcast to (/job:localhost/replica:0/task:0/device:GPU:0, /job:localhost/replica:0/task:0/device:GPU:1). INFO:tensorflow:Reduce to /job:localhost/replica:0/task:0/device:GPU:0 then broadcast to (/job:localhost/replica:0/task:0/device:GPU:0, /job:localhost/replica:0/task:0/device:GPU:1). INFO:tensorflow:Reduce to /job:localhost/replica:0/task:0/device:GPU:0 then broadcast to (/job:localhost/replica:0/task:0/device:GPU:0, /job:localhost/replica:0/task:0/device:GPU:1). INFO:tensorflow:Reduce to /job:localhost/replica:0/task:0/device:GPU:0 then broadcast to (/job:localhost/replica:0/task:0/device:GPU:0, /job:localhost/replica:0/task:0/device:GPU:1). INFO:tensorflow:Reduce to /job:localhost/replica:0/task:0/device:GPU:0 then broadcast to (/job:localhost/replica:0/task:0/device:GPU:0, /job:localhost/replica:0/task:0/device:GPU:1). INFO:tensorflow:Reduce to /job:localhost/replica:0/task:0/device:GPU:0 then broadcast to (/job:localhost/replica:0/task:0/device:GPU:0, /job:localhost/replica:0/task:0/device:GPU:1). INFO:tensorflow:Reduce to /job:localhost/replica:0/task:0/device:CPU:0 then broadcast to (/job:localhost/replica:0/task:0/device:CPU:0,). INFO:tensorflow:Reduce to /job:localhost/replica:0/task:0/device:CPU:0 then broadcast to (/job:localhost/replica:0/task:0/device:CPU:0,). INFO:tensorflow:Reduce to /job:localhost/replica:0/task:0/device:CPU:0 then broadcast to (/job:localhost/replica:0/task:0/device:CPU:0,). INFO:tensorflow:Reduce to /job:localhost/replica:0/task:0/device:CPU:0 then broadcast to (/job:localhost/replica:0/task:0/device:CPU:0,). INFO:tensorflow:Reduce to /job:localhost/replica:0/task:0/device:CPU:0 then broadcast to (/job:localhost/replica:0/task:0/device:CPU:0,). INFO:tensorflow:Reduce to /job:localhost/replica:0/task:0/device:CPU:0 then broadcast to (/job:localhost/replica:0/task:0/device:CPU:0,). INFO:tensorflow:Reduce to /job:localhost/replica:0/task:0/device:GPU:0 then broadcast to (/job:localhost/replica:0/task:0/device:GPU:0, /job:localhost/replica:0/task:0/device:GPU:1). INFO:tensorflow:Reduce to /job:localhost/replica:0/task:0/device:GPU:0 then broadcast to (/job:localhost/replica:0/task:0/device:GPU:0, /job:localhost/replica:0/task:0/device:GPU:1). INFO:tensorflow:Reduce to /job:localhost/replica:0/task:0/device:GPU:0 then broadcast to (/job:localhost/replica:0/task:0/device:GPU:0, /job:localhost/replica:0/task:0/device:GPU:1). 281/281 [] - 15s 53ms/step - loss: 2.0270 - sparse_categorical_accuracy: 0.4653 - sparse_top_k_categorical_accuracy: 0.7481 - val_loss: 1.7517 - val_sparse_categorical_accuracy: 0.5481 - val_sparse_top_k_categorical_accuracy: 0.7578 Epoch 2/10 281/281 [] - 4s 14ms/step - loss: 1.5206 - sparse_categorical_accuracy: 0.6045 - sparse_top_k_categorical_accuracy: 0.7938 - val_loss: 1.5715 - val_sparse_categorical_accuracy: 0.5993 - val_sparse_top_k_categorical_accuracy: 0.7983 Epoch 3/10 281/281 [] - 4s 14ms/step - loss: 1.2178 - sparse_categorical_accuracy: 0.6843 - sparse_top_k_categorical_accuracy: 0.8547 - val_loss: 1.5232 - val_sparse_categorical_accuracy: 0.6327 - val_sparse_top_k_categorical_accuracy: 0.8112 Epoch 4/10 281/281 [] - 4s 13ms/step - loss: 0.9127 - sparse_categorical_accuracy: 0.7648 - sparse_top_k_categorical_accuracy: 0.9113 - val_loss: 1.6527 - val_sparse_categorical_accuracy: 0.6296 - val_sparse_top_k_categorical_accuracy: 0.8201 Epoch 5/10 281/281 [] - 4s 14ms/step - loss: 0.6606 - sparse_categorical_accuracy: 0.8321 - sparse_top_k_categorical_accuracy: 0.9525 - val_loss: 1.8791 - val_sparse_categorical_accuracy: 0.6158 - val_sparse_top_k_categorical_accuracy: 0.8219 Epoch 6/10 281/281 [] - 4s 14ms/step - loss: 0.4919 - sparse_categorical_accuracy: 0.8799 - sparse_top_k_categorical_accuracy: 0.9725 - val_loss: 2.1282 - val_sparse_categorical_accuracy: 0.6037 - val_sparse_top_k_categorical_accuracy: 0.8112 Epoch 7/10 281/281 [] - 4s 14ms/step - loss: 0.3947 - sparse_categorical_accuracy: 0.9051 - sparse_top_k_categorical_accuracy: 0.9814 - val_loss: 2.3033 - val_sparse_categorical_accuracy: 0.6046 - val_sparse_top_k_categorical_accuracy: 0.8094 Epoch 8/10 281/281 [] - 4s 14ms/step - loss: 0.3335 - sparse_categorical_accuracy: 0.9207 - sparse_top_k_categorical_accuracy: 0.9863 - val_loss: 2.4255 - val_sparse_categorical_accuracy: 0.5993 - val_sparse_top_k_categorical_accuracy: 0.8099 Epoch 9/10 281/281 [] - 4s 14ms/step - loss: 0.2919 - sparse_categorical_accuracy: 0.9304 - sparse_top_k_categorical_accuracy: 0.9911 - val_loss: 2.5571 - val_sparse_categorical_accuracy: 0.6020 - val_sparse_top_k_categorical_accuracy: 0.8126 Epoch 10/10 281/281 [] - 4s 14ms/step - loss: 0.2617 - sparse_categorical_accuracy: 0.9342 - sparse_top_k_categorical_accuracy: 0.9937 - val_loss: 2.6700 - val_sparse_categorical_accuracy: 0.6077 - val_sparse_top_k_categorical_accuracy: 0.8148 CPU times: user 1min 2s, sys: 8.59 s, total: 1min 10s Wall time: 58.5 s从日志中可以观察到几个规律第 1 个 epoch 明显更慢15s/步级 53ms这是因为其中包含模型图构建、设备复制与首次 All-reduce 初始化等一次性开销从第 2 个 epoch 起稳定在4s 左右13~14ms/step训练指标随 epoch 稳步上升sparse_categorical_accuracy从 0.4653 提升到 0.9342sparse_top_k_categorical_accuracy最终达到 0.9937验证集指标val_*在第 1~3 epoch 上升后开始小幅波动呈现出典型的过拟合趋势训练 loss 持续下降至 0.2617验证 loss 则从 1.75 逐步升高到 2.6710 个 epoch 对这个小模型而言略多实际使用时可通过回调早停见 5-8,回调函数callbacks.md控制。六与单GPU、TPU训练方案的横向衔接多 GPU 训练只是加速训练选项之一本书在第 6 章提供了完整的三级加速方案三者的改造量都极小且共用同一套数据与模型代码方案关键改造新增代码量适用场景对应章节单 GPU通常无需改代码自动使用 GPU服务器共享场景可设置显存按需增长与可见设备04 行单卡即可满足显存与算力需求6-3,使用单GPU训练模型.md多 GPUMirroredStrategy()with strategy.scope()包裹模型创建与编译2 行单机多卡需要更大吞吐或更大有效批大小本文TPUTPUClusterResolver连接集群、TPUStrategy包裹模型共 6 行6 行Colab TPU8 核等云端加速6-5,使用TPU训练模型.md其中 TPU 方案6-5,使用TPU训练模型.md的 6 行代码为通过tf.distribute.cluster_resolver.TPUClusterResolver(tpugrpc:// os.environ[COLAB_TPU_ADDR])解析 TPU 集群地址、tf.config.experimental_connect_to_cluster(resolver)连接集群、tf.tpu.experimental.initialize_tpu_system(resolver)初始化 TPU 系统再以tf.distribute.experimental.TPUStrategy(resolver)包裹模型创建与编译——与本文的 MirroredStrategy 用法完全同构理解了本文的 scope 机制即可无缝迁移。七注意事项与适用边界代码运行环境本文范例依赖 Colab 的 GPU 环境原文档明确标注以下代码只能在 Colab 上才能正确执行本地环境需要自行安装 GPU 版 TensorFlow 与 CUDA并确保存在 ≥2 张可见 GPU或按第三节方式切分虚拟设备虚拟 GPU 的通信限制在虚拟 GPU 上 NCCL 不可用会自动回退为归约到单一设备再广播日志中的 WARNING 属正常现象不代表出错真实多卡环境下默认走 NCCL通信效率更高scope 是硬性要求模型以及优化器等带变量对象必须在strategy.scope()内创建与编译否则变量不会被镜像化策略无法生效——这是多 GPU 训练最容易踩的坑同步策略的语义MirroredStrategy 是同步数据并行每轮迭代需要等待所有设备完成梯度聚合后才更新参数因此各设备算力应尽量均衡建议使用同型号 GPU否则整体速度会被最慢的设备拖累有效批大小变化N 卡训练时全局有效批大小相当于原来的 N 倍每设备 BATCH_SIZE/N在大数据集上通常需要相应调大学习率这一点与单卡训练的超参数调优经验不同版本适用前提本书全部代码在 TensorFlow 2.1 上测试通过见 README.mdtf.distribute的相关 API如experimental前缀接口在新版本中可能被调整或迁移到稳定命名空间升级大版本后建议先核对 API 兼容性。至此你已经掌握了两行代码开启多 GPU 训练的完整方法论理解 MirroredStrategy 的同步镜像机制、会用虚拟设备在单卡上模拟多卡、并能在不修改模型与 fit 训练逻辑的前提下完成多卡训练。将这套模式与本书第 6 章其余方案6-2,训练模型的3种方法.md、6-3,使用单GPU训练模型.md、6-5,使用TPU训练模型.md组合使用即可根据手头硬件灵活选择加速方案。赞分享教程深度学习机器学习【免费下载链接】eat_tensorflow2_in_30_daysTensorflow2.0 is delicious, just eat it! 项目地址https://gitcode.com/gh_mirrors/ea/eat_tensorflow2_in_30_days点击查看免费下载相关推荐30天吃掉TensorFlow2六-4多GPU分布式训练实战——MirroredStrategy 数据并行原理与完整代码解析30天吃掉TensorFlow2六 4多GPU分布式训练实战——MirroredStrategy 数据并行原理与完整代码解析 本篇是《30天吃掉Tenso教程深度学习机器学习《30天吃掉那只 TensorFlow2.0》TensorFlow2 完整学习路线与实战技术指南《30天吃掉那只 TensorFlow2.0》TensorFlow2 完整学习路线与实战技术指南 本篇技术指南以开源项目 eat_tensorflow2_in教程深度学习机器学习新手必看openEuler/splitter常见问题与解决方案指南新手必看openEuler/splitter常见问题与解决方案指南 前往项目官网免费下载 https://ar.openeuler.org/ar/ http教程深度学习机器学习上一篇基于 VuePress 1.x 模板的文档站搭建默认主题首页布局Home Layout配置实战下一篇Apache Doris Remote UDF Java 实现指南基于 gRPC 的 RPC 函数服务开发实战创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考