Java調用Keras奥此、Tensorflow模型

實現(xiàn)python離線訓練模型已卷,Java在線預測部署梧田。查看原文

目前深度學習主流使用python訓練自己的模型,有非常多的框架提供了能快速搭建神經網絡的功能侧蘸,其中Keras提供了high-level的語法裁眯,底層可以使用tensorflow或者theano。

但是有很多公司后臺應用是用Java開發(fā)的讳癌,如果用python提供HTTP接口穿稳,對業(yè)務延遲要求比較高的話,仍然會有一定得延遲晌坤,所以能不能使用Java調用模型逢艘,python可以離線的訓練模型?(tensorflow也提供了成熟的部署方案TensorFlow Serving

手頭上有一個用Keras訓練的模型骤菠,網上關于Java調用Keras模型的資料不是很多它改,而且大部分是重復的,并且也沒有講的很詳細商乎。大致有兩種方案搔课,一種是基于Java的深度學習庫導入Keras模型實現(xiàn),另外一種是用tensorflow提供的Java接口調用。

Deeplearning4J

Eclipse Deeplearning4j is the first commercial-grade, open-source, distributed deep-learning library written for Java and Scala. Integrated with Hadoop and Spark, DL4J brings AIAI to business environments for use on distributed GPUs and CPUs.

Deeplearning4j目前支持導入Keras訓練的模型爬泥,并且提供了類似python中numpy的一些功能柬讨,更方便地處理結構化的數(shù)據(jù)。遺憾的是袍啡,Deeplearning4j現(xiàn)在只覆蓋了Keras <2.0版本的大部分Layer踩官,如果你是用Keras 2.0以上的版本,在導入模型的時候可能會報錯境输。

了解更多:
Keras Model Import: Supported Features
Importing Models From Keras to Deeplearning4j

Tensorflow

文檔蔗牡,Java的文檔很少,不過調用模型的過程也很簡單嗅剖。采用這種方式調用模型需要先將Keras導出的模型轉成tensorflow的protobuf協(xié)議的模型。

1信粮、Keras的h5模型轉為pb模型

在Keras中使用model.save(model.h5)保存當前模型為HDF5格式的文件中。
Keras的后端框架使用的是tensorflow强缘,所以先把模型導出為pb模型。在Java中只需要調用模型進行預測旅掂,所以將當前的graph中的Variable全部變成Constant赏胚,并且使用訓練后的weight。以下是freeze graph的代碼:

    def freeze_session(session, keep_var_names=None, output_names=None, clear_devices=True):
        """
        :param session: 需要轉換的tensorflow的session
        :param keep_var_names:需要保留的variable商虐,默認全部轉換constant
        :param output_names:output的名字
        :param clear_devices:是否移除設備指令以獲得更好的可移植性
        :return:
        """
        from tensorflow.python.framework.graph_util import convert_variables_to_constants
        graph = session.graph
        with graph.as_default():
            freeze_var_names = list(set(v.op.name for v in tf.global_variables()).difference(keep_var_names or []))
            output_names = output_names or []
            # 如果指定了output名字,則復制一個新的Tensor典勇,并且以指定的名字命名
            if len(output_names) > 0:
                for i in range(output_names):
                    # 當前graph中復制一個新的Tensor,指定名字
                    tf.identity(model.model.outputs[i], name=output_names[i])
            output_names += [v.op.name for v in tf.global_variables()]
            input_graph_def = graph.as_graph_def()
            if clear_devices:
                for node in input_graph_def.node:
                    node.device = ""
            frozen_graph = convert_variables_to_constants(session, input_graph_def,
                                                          output_names, freeze_var_names)
            return frozen_graph

該方法可以將tensor為Variable的graph全部轉為constant并且使用訓練后的weight鲫尊。注意output_name比較重要痴柔,后面Java調用模型的時候會用到沦偎。

在Keras中,模型是這么定義的:

    def create_model(self):
        input_tensor = Input(shape=(self.maxlen,), name="input")
        x = Embedding(len(self.text2id) + 1, 200)(input_tensor)
        x = Bidirectional(LSTM(128))(x)
        x = Dense(256, activation="relu")(x)
        x = Dropout(self.dropout)(x)
        x = Dense(len(self.id2class), activation='softmax', name="output_softmax")(x)
        model = Model(inputs=input_tensor, outputs=x)
        model.compile(loss='categorical_crossentropy',
                      optimizer='adam',
                      metrics=['accuracy'])

下面的代碼可以查看定義好的Keras模型的輸入豪嚎、輸出的name,這對之后Java調用有幫助舌涨。

print(model.input.op.name)
print(model.output.op.name)

訓練好Keras模型后扔字,轉換為pb模型:

from keras import backend as K
import tensorflow as tf

model.load_model("model.h5")
print(model.input.op.name)
print(model.output.op.name)
# 自定義output_names
frozen_graph = freeze_session(K.get_session(), output_names=["output"])
tf.train.write_graph(frozen_graph, "./", "model.pb", as_text=False)

### 輸出:
# input
# output_softmax/Softmax
# 如果不自定義output_name温技,則生成的pb模型的output_name為output_softmax/Softmax,如果自定義則以自定義名為output_name

運行之后會生成model.pb的模型舵鳞,這將是之后調用的模型琢蛤。

2、Java調用

新建一個maven項目博其,pom里面導入tensorflow包:

<dependency>
            <groupId>org.tensorflow</groupId>
            <artifactId>tensorflow</artifactId>
            <version>1.6.0</version>
</dependency>

核心代碼:

public void predict() throws Exception {
        try (Graph graph = new Graph()) {
            graph.importGraphDef(Files.readAllBytes(Paths.get(
                    "path/to/model.pb"
            )));
            try (Session sess = new Session(graph)) {
                // 自己構造一個輸入
                float[][] input = {{56, 632, 675, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}};
                try (Tensor x = Tensor.create(input);
                    // input是輸入的name,output是輸出的name
                    Tensor y = sess.runner().feed("input", x).fetch("output").run().get(0)) {
                    float[][] result = new float[1][y.shape[1]];
                    y.copyTo(result);
                    System.out.println(Arrays.toString(y.shape()));
                    System.out.println(Arrays.toString(result[0]));
                }
            }
        }
    }

Graph和Tensor對象都是需要通過close()方法顯式地釋放占用的資源背伴,代碼中使用了try-with-resources的方法實現(xiàn)的儡率。

至此,已經可以實現(xiàn)Keras離線訓練儿普,Java在線預測的功能。

?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末个绍,一起剝皮案震驚了整個濱河市浪汪,隨后出現(xiàn)的幾起案子巴柿,更是在濱河造成了極大的恐慌死遭,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,042評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件钉迷,死亡現(xiàn)場離奇詭異钠署,居然都是意外死亡,警方通過查閱死者的電腦和手機谐鼎,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,996評論 2 384
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來身害,“玉大人,你說我怎么就攤上這事塌鸯。” “怎么了丢习?”我有些...
    開封第一講書人閱讀 156,674評論 0 345
  • 文/不壞的土叔 我叫張陵淮悼,是天一觀的道長。 經常有香客問我袜腥,道長,這世上最難降的妖魔是什么鲤屡? 我笑而不...
    開封第一講書人閱讀 56,340評論 1 283
  • 正文 為了忘掉前任福侈,我火速辦了婚禮,結果婚禮上肪凛,老公的妹妹穿的比我還像新娘。我一直安慰自己翘鸭,他們只是感情好戳葵,可當我...
    茶點故事閱讀 65,404評論 5 384
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著拱烁,像睡著了一般。 火紅的嫁衣襯著肌膚如雪守伸。 梳的紋絲不亂的頭發(fā)上浦妄,一...
    開封第一講書人閱讀 49,749評論 1 289
  • 那天,我揣著相機與錄音剂娄,去河邊找鬼。 笑死和二,一個胖子當著我的面吹牛耳胎,可吹牛的內容都是我干的惯吕。 我是一名探鬼主播怕午,決...
    沈念sama閱讀 38,902評論 3 405
  • 文/蒼蘭香墨 我猛地睜開眼郁惜,長吁一口氣:“原來是場噩夢啊……” “哼堡距!你這毒婦竟也來了?” 一聲冷哼從身側響起羽戒,我...
    開封第一講書人閱讀 37,662評論 0 266
  • 序言:老撾萬榮一對情侶失蹤虎韵,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后包蓝,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經...
    沈念sama閱讀 44,110評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡衬吆,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 36,451評論 2 325
  • 正文 我和宋清朗相戀三年绳泉,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片冒嫡。...
    茶點故事閱讀 38,577評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡四苇,死狀恐怖,靈堂內的尸體忽然破棺而出月腋,到底是詐尸還是另有隱情瓣赂,我是刑警寧澤片拍,帶...
    沈念sama閱讀 34,258評論 4 328
  • 正文 年R本政府宣布,位于F島的核電站苫纤,受9級特大地震影響,放射性物質發(fā)生泄漏卷拘。R本人自食惡果不足惜祝高,卻給世界環(huán)境...
    茶點故事閱讀 39,848評論 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望褂策。 院中可真熱鬧,春花似錦耿焊、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,726評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至诊县,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間依痊,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,952評論 1 264
  • 我被黑心中介騙來泰國打工瓶摆, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留性宏,地道東北人。 一個月前我還...
    沈念sama閱讀 46,271評論 2 360
  • 正文 我出身青樓书斜,卻偏偏與公主長得像诬辈,于是被迫代替她去往敵國和親菩佑。 傳聞我的和親對象是個殘疾皇子凝化,可洞房花燭夜當晚...
    茶點故事閱讀 43,452評論 2 348

推薦閱讀更多精彩內容