TensorFlow on spark笔记

2024-09-03 21:08
文章标签 笔记 tensorflow spark

本文主要是介绍TensorFlow on spark笔记,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

背景:需要在spark2.4上面调用TensorFlow1.14的CNN模型处理图片,然鹅官方当前jar包有bug(libtensorflow_jni-1.14.0.jar),表现形式如下:

spark-shell --master local[10] --driver-memory 10G --jars s3://xxx/EMR/jars/tensorflow-1.14.0.jar,s3://xxx/EMR/jars/libtensorflow-1.14.0.jar,s3://xxx/EMR/jars/libtensorflow_jni-1.14.0.jar
 

import org.tensorflow.{Graph, Session, Tensor}
val graph = new Graph()
scala> Tensor.create(Array(1,2,3))
java.lang.UnsatisfiedLinkError: /mnt/tmp/tensorflow_native_libraries-1608707431068-0/libtensorflow_jni.so: libtensorflow_framework.so.1: cannot open shared object file: No such file or directory
  at java.lang.ClassLoader$NativeLibrary.load(Native Method)
  at java.lang.ClassLoader.loadLibrary0(ClassLoader.java:1934)
  at java.lang.ClassLoader.loadLibrary(ClassLoader.java:1817)
  at java.lang.Runtime.load0(Runtime.java:810)
  at java.lang.System.load(System.java:1088)
  at org.tensorflow.NativeLibrary.load(NativeLibrary.java:101)
  at org.tensorflow.TensorFlow.init(TensorFlow.java:66)
  at org.tensorflow.TensorFlow.<clinit>(TensorFlow.java:70)
  at org.tensorflow.Tensor.<clinit>(Tensor.java:853)
  ... 49 elided

 

尝试解决:

先试试Java命令直接运行含有TensorFlow的jar,为此先将依赖添加到环境变量中:

TF_TYPE="cpu" # Default processor is CPU. If you want GPU, set to "gpu"
OS=$(uname -s | tr '[:upper:]' '[:lower:]')
mkdir -p ./jni
curl -L "https://download.tensorflow.google.cn/libtensorflow/libtensorflow_jni-${TF_TYPE}-${OS}-x86_64-1.14.0.tar.gz" |   tar -xz -C ./jni
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100   305  100   305    0     0  10892      0 --:--:-- --:--:-- --:--:-- 10892
100   467  100   467    0     0   7915      0 --:--:-- --:--:-- --:--:--  7915
  0     0    0     0    0     0      0      0 --:--:-- --:--:-- --:--:--     0
100 49.8M  100 49.8M    0     0  5484k      0  0:00:09  0:00:09 --:--:-- 6412k

ll jni/
total 181268
lrwxrwxrwx 1 hadoop hadoop        28 Jan  1  2000 libtensorflow_framework.so -> libtensorflow_framework.so.1
lrwxrwxrwx 1 hadoop hadoop        33 Jan  1  2000 libtensorflow_framework.so.1 -> libtensorflow_framework.so.1.14.0
-r-xr-xr-x 1 hadoop hadoop  34748520 Jan  1  2000 libtensorflow_framework.so.1.14.0
-r-xr-xr-x 1 hadoop hadoop 150449736 Jan  1  2000 libtensorflow_jni.so
-r-xr-xr-x 1 hadoop hadoop    414358 Jan  1  2000 LICENSE

 

vi HelloTF.java

import org.tensorflow.Graph;
import org.tensorflow.Session;
import org.tensorflow.Tensor;
import org.tensorflow.TensorFlow;

public class HelloTF {
  public static void main(String[] args) throws Exception {
    try (Graph g = new Graph()) {
      final String value = "Hello from " + TensorFlow.version();

      try (Tensor t = Tensor.create(value.getBytes("UTF-8"))) {
        g.opBuilder("Const", "MyConst").setAttr("dtype", t.dataType()).setAttr("value", t).build();
      }
      try (Session s = new Session(g);
           Tensor output = s.runner().fetch("MyConst").run().get(0)) {
        System.out.println(new String(output.bytesValue(), "UTF-8"));
      }
    }
  }
}

javac -cp libtensorflow-1.14.0.jar HelloTF.java

 

java -cp libtensorflow-1.14.0.jar:. -Djava.library.path=./jni HelloTF
2020-12-23 07:04:36.287193: I tensorflow/core/platform/cpu_feature_guard.cc:142] Your CPU supports instructions that this TensorFlow binary was not compiled to use: AVX2 AVX512F FMA
2020-12-23 07:04:36.309812: I tensorflow/core/platform/profile_utils/cpu_utils.cc:94] CPU Frequency: 2999995000 Hz
2020-12-23 07:04:36.310521: I tensorflow/compiler/xla/service/service.cc:168] XLA service 0x7f2a90dba590 executing computations on platform Host. Devices:
2020-12-23 07:04:36.310542: I tensorflow/compiler/xla/service/service.cc:175]   StreamExecutor device (0): <undefined>, <undefined>
Hello from 1.14.0

export PATH="$PATH:/home/hadoop/jni"
source /etc/profile

添加环境变量后,在spark中问题依旧,但此时,至少能让Java后端调用.pb模型了。

 

最终解决办法:

在src-main-java中新建org.tensorflow包,并新建Java类NativeLibrary 覆盖原有的方法:

package org.tensorflow;import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;/*** 这个NativeLibrary会覆盖jar包里的方法,解决找不到tensorflow1.14 libtensorflow_framework.so.1的问题。* 参考:https://blog.csdn.net/handong01027/article/details/101371739* Helper class for loading the TensorFlow Java native library.** <p>The Java TensorFlow bindings require a native (JNI) library. This library* (libtensorflow_jni.so on Linux, libtensorflow_jni.dylib on OS X, tensorflow_jni.dll on Windows)* can be made available to the JVM using the java.library.path System property (e.g., using* -Djava.library.path command-line argument). However, doing so requires an additional step of* configuration.** <p>Alternatively, the native libraries can be packaed in a .jar, making them easily usable from* build systems like Maven. However, in such cases, the native library has to be extracted from the* .jar archive.** <p>NativeLibrary.load() takes care of this. First looking for the library in java.library.path* and failing that, it tries to find the OS and architecture specific version of the library in the* set of ClassLoader resources (under org/tensorflow/native/OS-ARCH). The resources paths used for* lookup must be consistent with any packaging (such as on Maven Central) of the TensorFlow Java* native libraries.*/
final class NativeLibrary {private static final boolean DEBUG =System.getProperty("org.tensorflow.NativeLibrary.DEBUG") != null;private static final String JNI_LIBNAME = "tensorflow_jni";public static void load() {if (isLoaded() || tryLoadLibrary()) {// Either:// (1) The native library has already been statically loaded, OR// (2) The required native code has been statically linked (through a custom launcher), OR// (3) The native code is part of another library (such as an application-level library)// that has already been loaded. For example, tensorflow/examples/android and// tensorflow/tools/android/inference_interface include the required native code in// differently named libraries.//// Doesn't matter how, but it seems the native code is loaded, so nothing else to do.return;}// Native code is not present, perhaps it has been packaged into the .jar file containing this.// Extract the JNI library itselffinal String jniLibName = System.mapLibraryName(JNI_LIBNAME);final String jniResourceName = makeResourceName(jniLibName);log("jniResourceName: " + jniResourceName);final InputStream jniResource =NativeLibrary.class.getClassLoader().getResourceAsStream(jniResourceName);// Extract the JNI's dependencyfinal String frameworkLibName =getVersionedLibraryName(System.mapLibraryName("tensorflow_framework"));final String frameworkResourceName = makeResourceName(frameworkLibName);log("frameworkResourceName: " + frameworkResourceName);final InputStream frameworkResource =NativeLibrary.class.getClassLoader().getResourceAsStream(frameworkResourceName);// Do not complain if the framework resource wasn't found. This may just mean that we're// building with --config=monolithic (in which case it's not needed and not included).if (jniResource == null) {throw new UnsatisfiedLinkError(String.format("Cannot find TensorFlow native library for OS: %s, architecture: %s. See "+ "https://github.com/tensorflow/tensorflow/tree/master/tensorflow/java/README.md"+ " for possible solutions (such as building the library from source). Additional"+ " information on attempts to find the native library can be obtained by adding"+ " org.tensorflow.NativeLibrary.DEBUG=1 to the system properties of the JVM.",os(), architecture()));}try {// Create a temporary directory for the extracted resource and its dependencies.final File tempPath = createTemporaryDirectory();// Deletions are in the reverse order of requests, so we need to request that the directory be// deleted first, so that it is empty when the request is fulfilled.tempPath.deleteOnExit();final String tempDirectory = tempPath.getCanonicalPath();if (frameworkResource != null) {extractResource(frameworkResource, frameworkLibName, tempDirectory);} else {log(frameworkResourceName+ " not found. This is fine assuming "+ jniResourceName+ " is not built to depend on it.");}System.load(extractResource(jniResource, jniLibName, tempDirectory));} catch (IOException e) {throw new UnsatisfiedLinkError(String.format("Unable to extract native library into a temporary file (%s)", e.toString()));}}private static boolean tryLoadLibrary() {try {System.loadLibrary(JNI_LIBNAME);return true;} catch (UnsatisfiedLinkError e) {log("tryLoadLibraryFailed: " + e.getMessage());return false;}}private static boolean isLoaded() {try {TensorFlow.version();log("isLoaded: true");return true;} catch (UnsatisfiedLinkError e) {return false;}}private static boolean resourceExists(String baseName) {return NativeLibrary.class.getClassLoader().getResource(makeResourceName(baseName)) != null;}private static String getVersionedLibraryName(String libFilename) {final String versionName = getMajorVersionNumber();// If we're on darwin, the versioned libraries look like blah.1.dylib.final String darwinSuffix = ".dylib";if (libFilename.endsWith(darwinSuffix)) {final String prefix = libFilename.substring(0, libFilename.length() - darwinSuffix.length());if (versionName != null) {final String darwinVersionedLibrary = prefix + "." + versionName + darwinSuffix;if (resourceExists(darwinVersionedLibrary)) {return darwinVersionedLibrary;}} else {// If we're here, we're on darwin, but we couldn't figure out the major version number. We// already tried the library name without any changes, but let's do one final try for the// library with a .so suffix.final String darwinSoName = prefix + ".so";if (resourceExists(darwinSoName)) {return darwinSoName;}}} else if (libFilename.endsWith(".so")) {// Libraries ending in ".so" are versioned like "libfoo.so.1", so try that.final String versionedSoName = libFilename + "." + versionName;if (versionName != null && resourceExists(versionedSoName)) {return versionedSoName;}}// Otherwise, we've got no idea.return libFilename;}/*** Returns the major version number of this TensorFlow Java API, or {@code null} if it cannot be* determined.*/private static String getMajorVersionNumber() {String version = NativeLibrary.class.getPackage().getImplementationVersion();// expecting a string like 1.14.0, we want to get the first '1'.int dotIndex;if (version == null || (dotIndex = version.indexOf('.')) == -1) {return "1";}String majorVersion = version.substring(0, dotIndex);try {Integer.parseInt(majorVersion);return majorVersion;} catch (NumberFormatException unused) {return null;}}private static String extractResource(InputStream resource, String resourceName, String extractToDirectory) throws IOException {final File dst = new File(extractToDirectory, resourceName);dst.deleteOnExit();final String dstPath = dst.toString();log("extracting native library to: " + dstPath);final long nbytes = copy(resource, dst);log(String.format("copied %d bytes to %s", nbytes, dstPath));return dstPath;}private static String os() {final String p = System.getProperty("os.name").toLowerCase();if (p.contains("linux")) {return "linux";} else if (p.contains("os x") || p.contains("darwin")) {return "darwin";} else if (p.contains("windows")) {return "windows";} else {return p.replaceAll("\\s", "");}}private static String architecture() {final String arch = System.getProperty("os.arch").toLowerCase();return (arch.equals("amd64")) ? "x86_64" : arch;}private static void log(String msg) {if (DEBUG) {System.err.println("org.tensorflow.NativeLibrary: " + msg);}}private static String makeResourceName(String baseName) {return "org/tensorflow/native/" + String.format("%s-%s/", os(), architecture()) + baseName;}private static long copy(InputStream src, File dstFile) throws IOException {FileOutputStream dst = new FileOutputStream(dstFile);try {byte[] buffer = new byte[1 << 20]; // 1MBlong ret = 0;int n = 0;while ((n = src.read(buffer)) >= 0) {dst.write(buffer, 0, n);ret += n;}return ret;} finally {dst.close();src.close();}}// Shamelessly adapted from Guava to avoid using java.nio, for Android API// compatibility.private static File createTemporaryDirectory() {File baseDirectory = new File(System.getProperty("java.io.tmpdir"));String directoryName = "tensorflow_native_libraries-" + System.currentTimeMillis() + "-";for (int attempt = 0; attempt < 1000; attempt++) {File temporaryDirectory = new File(baseDirectory, directoryName + attempt);if (temporaryDirectory.mkdir()) {return temporaryDirectory;}}throw new IllegalStateException("Could not create a temporary directory (tried to make "+ directoryName+ "*) to extract TensorFlow native libraries.");}private NativeLibrary() {}
}

 

 

参考:

https://blog.csdn.net/noiplcx/article/details/83270552

https://blog.csdn.net/handong01027/article/details/101371739

 

这篇关于TensorFlow on spark笔记的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1134045

相关文章

【学习笔记】 陈强-机器学习-Python-Ch15 人工神经网络(1)sklearn

系列文章目录 监督学习:参数方法 【学习笔记】 陈强-机器学习-Python-Ch4 线性回归 【学习笔记】 陈强-机器学习-Python-Ch5 逻辑回归 【课后题练习】 陈强-机器学习-Python-Ch5 逻辑回归(SAheart.csv) 【学习笔记】 陈强-机器学习-Python-Ch6 多项逻辑回归 【学习笔记 及 课后题练习】 陈强-机器学习-Python-Ch7 判别分析 【学

系统架构师考试学习笔记第三篇——架构设计高级知识(20)通信系统架构设计理论与实践

本章知识考点:         第20课时主要学习通信系统架构设计的理论和工作中的实践。根据新版考试大纲,本课时知识点会涉及案例分析题(25分),而在历年考试中,案例题对该部分内容的考查并不多,虽在综合知识选择题目中经常考查,但分值也不高。本课时内容侧重于对知识点的记忆和理解,按照以往的出题规律,通信系统架构设计基础知识点多来源于教材内的基础网络设备、网络架构和教材外最新时事热点技术。本课时知识

论文阅读笔记: Segment Anything

文章目录 Segment Anything摘要引言任务模型数据引擎数据集负责任的人工智能 Segment Anything Model图像编码器提示编码器mask解码器解决歧义损失和训练 Segment Anything 论文地址: https://arxiv.org/abs/2304.02643 代码地址:https://github.com/facebookresear

数学建模笔记—— 非线性规划

数学建模笔记—— 非线性规划 非线性规划1. 模型原理1.1 非线性规划的标准型1.2 非线性规划求解的Matlab函数 2. 典型例题3. matlab代码求解3.1 例1 一个简单示例3.2 例2 选址问题1. 第一问 线性规划2. 第二问 非线性规划 非线性规划 非线性规划是一种求解目标函数或约束条件中有一个或几个非线性函数的最优化问题的方法。运筹学的一个重要分支。2

【C++学习笔记 20】C++中的智能指针

智能指针的功能 在上一篇笔记提到了在栈和堆上创建变量的区别,使用new关键字创建变量时,需要搭配delete关键字销毁变量。而智能指针的作用就是调用new分配内存时,不必自己去调用delete,甚至不用调用new。 智能指针实际上就是对原始指针的包装。 unique_ptr 最简单的智能指针,是一种作用域指针,意思是当指针超出该作用域时,会自动调用delete。它名为unique的原因是这个

查看提交历史 —— Git 学习笔记 11

查看提交历史 查看提交历史 不带任何选项的git log-p选项--stat 选项--pretty=oneline选项--pretty=format选项git log常用选项列表参考资料 在提交了若干更新,又或者克隆了某个项目之后,你也许想回顾下提交历史。 完成这个任务最简单而又有效的 工具是 git log 命令。 接下来的例子会用一个用于演示的 simplegit

记录每次更新到仓库 —— Git 学习笔记 10

记录每次更新到仓库 文章目录 文件的状态三个区域检查当前文件状态跟踪新文件取消跟踪(un-tracking)文件重新跟踪(re-tracking)文件暂存已修改文件忽略某些文件查看已暂存和未暂存的修改提交更新跳过暂存区删除文件移动文件参考资料 咱们接着很多天以前的 取得Git仓库 这篇文章继续说。 文件的状态 不管是通过哪种方法,现在我们已经有了一个仓库,并从这个仓

忽略某些文件 —— Git 学习笔记 05

忽略某些文件 忽略某些文件 通过.gitignore文件其他规则源如何选择规则源参考资料 对于某些文件,我们不希望把它们纳入 Git 的管理,也不希望它们总出现在未跟踪文件列表。通常它们都是些自动生成的文件,比如日志文件、编译过程中创建的临时文件等。 通过.gitignore文件 假设我们要忽略 lib.a 文件,那我们可以在 lib.a 所在目录下创建一个名为 .gi

取得 Git 仓库 —— Git 学习笔记 04

取得 Git 仓库 —— Git 学习笔记 04 我认为, Git 的学习分为两大块:一是工作区、索引、本地版本库之间的交互;二是本地版本库和远程版本库之间的交互。第一块是基础,第二块是难点。 下面,我们就围绕着第一部分内容来学习,先不考虑远程仓库,只考虑本地仓库。 怎样取得项目的 Git 仓库? 有两种取得 Git 项目仓库的方法。第一种是在本地创建一个新的仓库,第二种是把其他地方的某个

Git 的特点—— Git 学习笔记 02

文章目录 Git 简史Git 的特点直接记录快照,而非差异比较近乎所有操作都是本地执行保证完整性一般只添加数据 参考资料 Git 简史 众所周知,Linux 内核开源项目有着为数众多的参与者。这么多人在世界各地为 Linux 编写代码,那Linux 的代码是如何管理的呢?事实是在 2002 年以前,世界各地的开发者把源代码通过 diff 的方式发给 Linus,然后由 Linus