14.2 保存和加载tf.Model模型
TensorFlow.js提供了保存和加载模型的功能,这些模型可以是使用LayersAPI创建的或从现有TensorFlow模型转换过来的。可能是我们自己训练过的模型,也可能是别人训练的模型。使用Layers API的一个主要好处是使用它创建的模型是可序列化的,这就是我们将在本节内容中探讨的内容。
14.2.1 保存tf.Model
在tf.Model和tf.Sequential中同时提供了函数 model.save(),允许我们保存一个模型的拓扑结构(topology)和权重(weights) 。
- 拓扑结构(Topology):是一个描述模型结构的文件(例如它使用的了哪些操作,包含对存储在外部的模型权重的引用。
- 权重(Weights):是以有效格式存储给定模型权重的二进制文件,通常存储在与拓扑结构相同的文件夹中。
例如下面是一段保存模型的代码:
const saveResult = await model.save('localstorage://my-model-1');
对上述代码的具体说明如下:
- 函数 model.save()的参数是以 scheme 字符串开头的URL的字符串参数(简称 scheme),描述了想要保存的模型地址的类型。在上述代码中,使用参数“localstorage:// scheme”将模型保存到本地存储。
- 在scheme 之后是路径(path),在上述代码中,路径是'my-model-1'。
- 函数 model.save()是异步的。
- 函数 model.save()的返回值是一个 JSON 对象,包含一些可能有用的信息,例如模型的拓扑结构和权重的大小。
在 node.js中保存模型时,不会阻碍模型在浏览器中被加载。
在下面的内容中,将介绍几种保存模型的不同方案。
(1)本地存储 (仅限浏览器),格式是Scheme: localstorage://,例如下面的代码:
await model.save('localstorage://my-model');
这样可以在浏览器的本地存储中以名称 my-model 来保存模型。这样存储能够在浏览器刷新后保持不变,而当存储空间成为问题时,用户或浏览器本身可以清除本地存储。每个浏览器还可以对给定域在本地的存储空间设定限额。
(2)IndexedDB (仅限浏览器),格式是Scheme: indexeddb://,例如
await model.save('indexeddb://my-model');
这样会将模型保存到浏览器的IndexedDB存储中。与本地存储一样,在刷新后仍然存在,同时往往也对存储的对象的大小有较大的限制。
(3)文件下载 (仅限浏览器),格式是Scheme: downloads://,例如:
await model.save('downloads://my-model');
这会让浏览器将模型文件下载到用户的机器上,并生成两个文件:
- 一个名为 [my-model].json的JSON文件,它包含了模型的拓扑结构和接下来将要介绍的权重文件的引用。
- 一个二进制文件,其中包含名为 [my-model].weights.bin 的权重值。
我们可以更换 [my-model]的名称,以获得一个不同的名称的文件。因为“.json”使用相对路径指向“.bin”,所以两个文件需要被保存在同一个文件夹中。
(4)HTTP(S) Request方式,格式是Scheme: http://或https://,例如:
await model.save('http://model-server.domain/upload')
这样会创建一个Web请求,将模型保存到远程服务器。应该控制该远程服务器,以便确保它能够处理该请求。模型将通POST请求发送到指定的HTTP服务器。POST 请求的body遵循multipart/form-data格式,由以下两个文件组成
- 一个名为 model.json 的 JSON 文件,其中包含拓扑结构和对下面描述的权重文件的引用。
- 一个二进制文件,其中包含名为 [my-model].weights.bin 的权重值。
请注意,上述两个文件的名称需要与上述介绍中的保持完全相同(因为名称内置于函数中,无法更改)。 此 api 文档包含一个 Python 代码片段,演示了如何使用 flask web 框架来处理源自 save 的请求。
通常,必须向 HTTP 服务器传递更多参数或请求头(例如,用于身份验证,或者如果要指定应保存模型的文件夹)。您可以通过替换 tf.io.browserHTTPRequest 函数中的 URL字符串参数来获得对来自 save 函数的请求在这些方面的细粒度控制。这个API在控制 HTTP 请求方面提供了更大的灵活性。例如:
await model.save(tf.io.browserHTTPRequest(
'http://model-server.domain/upload',
{method: 'PUT', headers: {'header_key_1': 'header_value_1'} }));
(5)本机文件系统 (仅限于Node.js),格式是Scheme: file://,例如:
await model.save('file:///path/to/my-model');
在运行Node.js后可以直接访问文件系统并且保存模型,上述命令会将两个如下文件保存到在scheme之后指定的path中。
- 一个名为 model.json 的 JSON 文件,其中包含拓扑结构和对下面描述的权重文件的引用。
- 一个二进制文件,其中包含名为model.weights.bin的权重值。
请注意,这两个文件的名称将始终与上面指定的完全相同(该名称内置于函数中)。
14.2.2 加载tf.Model
如果使用上述方法之一保存模型,那么接下来可以使用 tf.loadLayersModel API来加载这个模型。首先让我们看一下如下加载模型的代码:
const model = await tf.loadLayersModel('localstorage://my-model-1');
对上述代码的具体说明如下:
- 函数loadLayersModel()使用以 scheme开头的类似URL的字符串参数,描述了我们试图从中加载模型的目标类型。
- scheme由path指定,在上述例子中的路径为my-model-1。
- URL字符串可以被替换为一个符合IOHandler接口的对象。
- 函数tf.loadLayersModel()是异步的。
- 函数tf.loadLayersModel的返回值是 tf.Model。
在下面的内容中,将介绍加载模型的不同方案。
(1)本地存储 (仅限浏览器),格式是Scheme: localstorage://,例如:
const model = await tf.loadLayersModel('localstorage://my-model');
这将从浏览器的本地存储加载一个名为my-model模型。
(2)IndexedDB (仅限浏览器),格式是Scheme: indexeddb://,例如:
const model = await tf.loadLayersModel('indexeddb://my-model');
这将从浏览器的IndexedDB中加载一个模型。
(3)HTTP(S),格式是Scheme: http:// or https://,例如:
const model = await tf.loadLayersModel('http://model-server.domain/download/model.json');
这将从HTTP端加载模型,在加载JSON文件后,函数将请求对应的JSON文件引用的“.bin”文件。
(4)本机文件系统 (仅限于Node.js),格式是Scheme: file://,例如:
const model = await tf.loadLayersModel('file://path/to/my-model/model.json');
当运行在Node.js上时,可以直接访问文件系统并且从那里加载模型。注意,在上面的函数调用中引用的是model.json文件本身(而在保存时,我们指定一个文件夹)。相应的“.bin”文件需要和JSON文件在同一个文件夹中。
(5)使用 IOHandlers 加载模型
如果上述方案没有满足我们的需求,还可以使用IOHandler执行自定义的加载行为。在Tensorflow.js的IOHandler中提供了函数tf.io.browserFiles(),功能是供浏览器用户在浏览器中上传文件。