Java调用Python深度学习模型完成AI输入输出
对象:DeepFaceLab
在Java应用中使用Python训练的算法模型
- Java代码下载相应jar包(Jython)直接调用Python代码。这样做,Java应用太过于依赖Python环境。也可以将Python代码打包为jar包,然后使用Java代码调用,但很多第三方库并不能实现打包成jar包。
- Java代码通过操作系统命令行调用,Java的ProcessBuilder API可以直接调用Python脚本运行。
- 将Python训练的模型参数保存到文本中,使用java代码重现模型的预测算法。这种,工作量很大,而且出现bug的几率也大大增加。最重要的是,很多深度学习的框架就没法使用了。
- 使用Python进程运行深度学习中的训练模型,在Java应用程序中调用Python进程提供的服务。Python编写的程序毕竟在Python环境中执行最有效率。而且Python应用和Java应用可以运行在不同服务器上,通过进程的远程访问调用。
- 使用 Runtime.getRuntime () 执行Python脚本,可输入输出参数。
- Java调用Shell方式本机运行,到资源管理器输入输出。
- 将机器学习模型保存为 pmml 文件,然后 java 调用 pmml 文件。这种方法是网上最常见的方法,进行上线部署的时候,不会依赖于 python 环境。但不是所有的机器学习模型都可以保存为PMML文件。
- Python REST API,把 Python 算法模型部署为 REST API,在 Java 代码中通过 HTTP 请求调用。
推荐
使用 Runtime.getRuntime () 执行 Python 脚本文件。Runtime.getRuntime ().exec ()方法是用来在一个单独的进程中执行一个命令或脚本的。这个方法的底层实现其实就是用的ProcessBuilder类,它可以更方便地设置子进程的属性和输入输出流。Runtime.getRuntime ().exec ()方法并不是使用socket来通信的,而是使用了操作系统提供的接口。
一般来说,socket调用深度学习模型需要通过网络传输数据,可能会有更多的开销和不稳定性。而Runtime.getRuntime ()调用深度学习模型则是在本地执行命令或脚本,可能会有更好的性能和兼容性。但这也要看具体的场景和需求,没有一个绝对的答案。考虑性能和效率,不建议既有Java的Web服务,又有Python的Web服务。如果这样的话,建议通过进程来实现Java程序和Python程序的通信,走Socket即可。最终实现,在 Java 应用程序中调用 Python 进程提供的服务。
Python REST API,嵌套学习模型,开发Django之类的Python框架,把项目封装为 Web 应用。
Runtime.getRuntime () Python脚本
无输入参数
Python脚本文件
1 | import numpy as np |
Java调用程序
1 | import java.io.BufferedReader; |
有输入参数1
Python脚本文件
1 | def add(a,b): |
Java调用程序
1 | package com.test; |
有参数输入2
Python脚本文件
1 | import sys |
Java调用程序
1 | import java.io.BufferedReader; |
中文乱码问题解决
用 Runtime.getRuntime.exec () 调用 Python 脚本时,Java 端捕获脚本有中文输出时,输出的中文可能是乱码,因为 Python 安装在 Windows 环境下的默认编码格式是 GBK。
解决方法:
在被调用的脚本的开头增加如下代码,一定要添加到其他依赖模块 import 之前。
1 | import io |
Runtime.getRuntime () Shell脚本
简介
在 Linux 中运行 Java 程序时,需要调用一些 Shell 命令和脚本。而 Runtime.getRuntime ().exec () 方法给我们提供了这个功能,而且 Runtime.getRuntime () 给我们提供了以下几种 exec () 方法:
1 | Process exec(String command) |
如果参数中如果没有 envp 参数或设为 null,表示调用命令将在当前程序执行的环境中执行;如果没有 dir 参数或设为 null,表示调用命令将在当前程序执行的目录中执行,因此调用到其他目录中的文件和脚本最好使用绝对路径。
各个参数的含义:
- cmdarray: 包含所调用命令及其参数的数组。
- command: 一条指定的系统命令。
- envp: 字符串数组,其中每个元素的环境变量的设置格式为 name=value;如果子进程应该继承当前进程的环境,则该参数为 null。
- dir: 子进程的工作目录;如果子进程应该继承当前进程的工作目录,则该参数为 null。
Demo
Shell脚本
shell 脚本运行指令为 sh **.sh args。注意,shell 脚本必须有执行权限,比如部署后 chmod -R 777 xx.sh 赋权。
1 | !/bin/sh |
Java代码
1 | public static void invokeShell(){ |
DeepFaceLab Shell脚本
原始脚本位置:https://github.com/nagadit/DeepFaceLab_Linux/tree/master/scripts
使用场景:提前训练模型模板,指定新的src图片,dst不改变,生成新的合成人脸。
模板为模型 + data_dst,指定输入图片,指定输出路径。
训练过程中,model的参数会改变,其他参数不改变。所以建议copy模板model到IO的model,使用IO的model进行训练,保存model以导出合成图片。图片导出完成后,删除IO的model。模板的model自始至终不改变。
环境初始化脚本 env.sh
1 | !/usr/bin/env bash |
源素材生成目标图片 2_extract_image_from_data_src.sh
源素材为图片,图片到图片的extract
1 | !/usr/bin/env bash |
强调:env.sh中的局部变量值可以传递到下文,不需要用export方式,export方式在并发场景下,变量会冲突。
注意:使用bash运行sh脚本。
提取SRC人脸关键数据 4_data_src_extract_faces_S3FD.sh
1 | !/usr/bin/env bash |
提取data_dst-SRC人脸数据
1 | !/usr/bin/env bash |
训练模型 6_train_SAEHD_no_preview.sh
1 | !/usr/bin/env bash |
合成输出 7_merge_SAEHD.sh
1 | !/usr/bin/env bash |
合并全过程脚本 env_extract_faces_train_merge.sh
1 | !/usr/bin/env bash |
expect脚本 expect_deep_face_lab.sh
1 | !/usr/bin/expect |
expect脚本环境安装 Ubuntu
sudo apt-get install expect
执行expect脚本
expect expect_deep_face_lab.sh xxx yyy