如何防止商用的深度学习模型源码泄露? - 知乎

保护商用的深度学习模型模型源码,最重要的就是保护模型。模型分为结构和权重两个部分,所以保护模型结构就需要在存储模型时不存储结构,比如 PyTorch 不要直接 torch.save(model, xxx),要存 torch.save(model.state_dict(), xxx)

Nuitka这个库可以把Python代码编译成可执行文件,从而保护代码逻辑以及模型结构。

User Manual​nuitka.net图标

模型权重可以通过随机加减乘除一个数,来避免对方直接自己写代码加载权重。虽然对方也可以通过反编译你的代码来强行推出你的加减乘除逻辑,不过这个成本比自己训模型还高。

没有 100%的保护,只要逆向成本比正向成本高就行了。

下面是 Nuitka 的安全性测试

比如下面一段简单的函数:

def f(x):
    return x + 666


if __name__ == '__main__':
    print(f'请输入:')
    print(f'结果:{f(int(input()))}')

交互效果:

请输入:
123
结果:789

如果没有任何保护,直接把源代码传给对方,那么对方可以直接看到你的内部逻辑。

假设使用 pyinstaller 来打包,也会存在被反编译的风险:

https://zhuanlan.zhihu.com/p/109266820​zhuanlan.zhihu.com图标

那么我们尝试使用 Nuitka 打包来试试看:

(base) ➜  test python -m nuitka test20210208.py
Nuitka:INFO: Starting Python compilation.
Nuitka:INFO: Completed Python level compilation and optimization.
Nuitka:INFO: Generating source code for C backend compiler.
Nuitka:INFO: Running data composer tool for optimal constant value handling.
Nuitka:INFO: Running C level backend compilation via Scons.
Nuitka-Scons:INFO: Backend C compiler: clang (clang).
Nuitka-Scons:WARNING: You are not using ccache.
Nuitka:INFO: Keeping build directory 'test20210208.build'.
Nuitka:INFO: Successfully created 'test20210208.bin'.

目录结构:

test20210208.bin
test20210208.py
test20210208.build
├── @link_input.txt
├── __bytecode.const
├── __constants.bin
├── __constants.c
├── __constants.const
├── __constants.h
├── __constants.o
├── __constants_data.c
├── __constants_data.o
├── __helpers.c
├── __helpers.h
├── __helpers.o
├── __loader.c
├── __loader.o
├── build_definitions.h
├── module.__main__.c
├── module.__main__.const
├── module.__main__.o
├── scons-report.txt
└── static_src
    ├── CompiledCellType.c -> /usr/local/anaconda3/lib/python3.8/site-packages/nuitka/build/static_src/CompiledCellType.c
    ├── CompiledCellType.o
    ├── CompiledCodeHelpers.c -> /usr/local/anaconda3/lib/python3.8/site-packages/nuitka/build/static_src/CompiledCodeHelpers.c
    ├── CompiledCodeHelpers.o
    ├── CompiledFunctionType.c -> /usr/local/anaconda3/lib/python3.8/site-packages/nuitka/build/static_src/CompiledFunctionType.c
    ├── CompiledFunctionType.o
    ├── CompiledGeneratorType.c -> /usr/local/anaconda3/lib/python3.8/site-packages/nuitka/build/static_src/CompiledGeneratorType.c
    ├── CompiledGeneratorType.o
    ├── InspectPatcher.c -> /usr/local/anaconda3/lib/python3.8/site-packages/nuitka/build/static_src/InspectPatcher.c
    ├── InspectPatcher.o
    ├── MainProgram.c -> /usr/local/anaconda3/lib/python3.8/site-packages/nuitka/build/static_src/MainProgram.c
    ├── MainProgram.o
    ├── MetaPathBasedLoader.c -> /usr/local/anaconda3/lib/python3.8/site-packages/nuitka/build/static_src/MetaPathBasedLoader.c
    └── MetaPathBasedLoader.o

可以看到,.py 文件先被转成了 .c 文件,然后被编译成 .o 文件,最后合并成 .bin 可执行文件。

我们试一试运行这个可执行文件:

(base) ➜  test ./test20210208.bin
请输入:
123
结果:789

逻辑是没问题的。

从 bin 到 C 是不可逆的,从 C 到 Python 也是不可逆的,因此代码是安全的。

另外我们再尝试一个更有意思的方法,编译成动态链接库:

(base) ➜  test python -m nuitka --module test20210208.py
Nuitka:INFO: Starting Python compilation.
Nuitka:INFO: Completed Python level compilation and optimization.
Nuitka:INFO: Generating source code for C backend compiler.
Nuitka:INFO: Running data composer tool for optimal constant value handling.
Nuitka:INFO: Running C level backend compilation via Scons.
Nuitka-Scons:INFO: Backend C compiler: clang (clang).
Nuitka-Scons:WARNING: You are not using ccache.
Nuitka:INFO: Keeping build directory 'test20210208.build'.
Nuitka:INFO: Successfully created 'test20210208.cpython-38-darwin.so'.

编译好了以后,我们可以把 .so 文件传给对方,让他自己去调用。

这里我们把 .so 拷到一个新的目录去调用:

我们可以看到,目录下只有一个 .so,没有任何 Python 文件,但是代码逻辑可以正常运行,并且使用 inspect.getsource 函数,无法看到源代码,只能提示 OSError: could not get source code。

代码安全性同上,从 .so 到 C 不可逆,从 C 到 Python 不可逆,因此代码是安全的。

    • *

补充说明:评论区有些人表示 .so 可以反汇编,然后导出 C 代码,但是这个 C 完全不是原来Python 导出的 C,而是几乎等同于汇编代码的 C,是无法推回 Python 的。


原网址: 访问
创建于: 2021-02-21 10:03:52
目录: default
标签: 无

请先后发表评论
  • 最新评论
  • 总共0条评论