在modelarts里使用自定義算法進行訓(xùn)練、導(dǎo)入模型、部署服務(wù)
本文介紹在ModelArts里使用自定義算法進行訓(xùn)練、導(dǎo)入模型、部署服務(wù)的過程。

如果你用過了ModelArts的自動學(xué)習(xí),然后你覺得自動學(xué)習(xí)過于自動了,想試試不那么自動的;
或者你用過了Modelarts的市場訂閱算法(以前叫預(yù)置算法),然后你覺得只是把別人寫好的攻略再重復(fù)一遍,你還想嘗試一點更新的東西;
那你也許可能對本文有一點感興趣,雖然這里的過程結(jié)束后,沒有生產(chǎn)出有任何業(yè)務(wù)意義的服務(wù),但是你知道了這個流程,不管有沒有業(yè)務(wù)意義,都是這樣的流程。
首先,自定義算法,就是自己可以比較自由的控制的算法。
這里用的算法,是一個最最簡單的,一元一次方程的線性回歸的算法。
數(shù)據(jù)?為簡單起見,不需要準備,不需要輸入,算法自己包含了。
算法的思路是這樣的:
1.自己準備數(shù)據(jù),就是一些數(shù)字,先是x軸上的100個數(shù)字。然后是y軸上的100個數(shù)字,y和x的關(guān)系是:y=2x+1+一個噪聲值
2.假裝我們不知道x和y之間的關(guān)系,我們的算法就是來尋找這個關(guān)系。每一對x和y的值,都是算法的輸入,而算法的目標,就是找出系數(shù)2和常量1。在tf里,x和y就是占位符,而要找出的系數(shù)和常量,就是變量。
3.算法的尋找的方法,是損失函數(shù),和優(yōu)化器。談到損失函數(shù),那這個應(yīng)該是有監(jiān)督學(xué)習(xí)吧,沒有標簽,怎么計算損失呢?
4.有了方法后,就是去做,一遍遍的做,反正機器也是不知道累的,這個算法簡單,秒完。
有了數(shù)據(jù),然后數(shù)據(jù)配合算法跑完,變量/參數(shù)就算出來了,這個時候要把成果保存下來。
好了,上面的這些,寫道一個py文件tf_modelart.py里,就可以作為自定義算法來到Modelarts里做訓(xùn)練了。
# -*- coding: utf-8 -*- import os import numpy as np import tensorflow.compat.v1 as tf tf.disable_eager_execution() tf.flags.DEFINE_integer('max_steps', 1000, 'number of training iterations.') tf.flags.DEFINE_string('data_url', '', 'dataset directory.') tf.flags.DEFINE_string('train_url', '', 'saved model directory.') FLAGS = tf.flags.FLAGS def model(x,w,b): return tf.multiply(x,w)+b def main(*args): #輸入數(shù)據(jù)目錄這里沒有使用;因為代碼里自己生成了數(shù)據(jù) print('^_^the data_url is ',FLAGS.data_url) np.random.seed(5) #生成100個點,取值范圍[-1,1] x_data=np.linspace(-1,1,100) #后面是加一個噪聲 不然是一條直線 ; *是把元組展開 print(*x_data.shape) y_data=2*x_data + 1.0 + np.random.randn(*x_data.shape)*0.4 print('^_^start training...') #二個占位符是訓(xùn)練時傳入的 x=tf.placeholder('float',name='x') y=tf.placeholder('float',name='y') #這二個變量是來保存和更新參數(shù)的 w=tf.Variable(1.0,name='w0') b=tf.Variable(0.0,name='b0') pred=model(x,w,b) #設(shè)置訓(xùn)練超參 train_epochs=2 learning_rate=0.05 #損失函數(shù) loss_func=tf.reduce_mean(tf.square(y-pred)) #優(yōu)化器 optimizer=tf.train.GradientDescentOptimizer(learning_rate).minimize(loss_func) #可以開始跑訓(xùn)練了 sess=tf.Session() init=tf.global_variables_initializer() sess.run(init) for epoch in range(train_epochs): for xs,ys in zip(x_data,y_data): _,loss=sess.run([optimizer,loss_func],feed_dict={x:xs,y:ys}) print('^_^Done training!') #保存模型 signature_key = 'test_signature' input_key = 'input_x' output_key = 'output' builder=tf.saved_model.builder.SavedModelBuilder(os.path.join(FLAGS.train_url,'model')) inputs = {input_key : tf.saved_model.utils.build_tensor_info(x)} outputs = {output_key : tf.saved_model.utils.build_tensor_info(pred)} signature = tf.saved_model.signature_def_utils.build_signature_def(inputs, outputs, 'test_sig_name') builder.add_meta_graph_and_variables(sess,['igraphtag'],{signature_key:signature}) builder.save() print('^_^export train dir is ',FLAGS.train_url) if __name__ == '__main__': tf.app.run(main=main)
訓(xùn)練管理>訓(xùn)練作業(yè)>創(chuàng)建截圖
這里train_url和data_url是根據(jù)上面的選擇帶出的,還可以增加其他可配置化的參數(shù),比如一些超參,訓(xùn)練的epoch和學(xué)習(xí)率等,這里為了簡化,都略過。
運行成功后,保存了模型到OBS里
然后,在modelarts里,有一個模型導(dǎo)入的步驟要做,這樣會將模型封進image,以利于后續(xù)部署。
而在模型導(dǎo)入之前,還需要做一件事件,那就是確定模型對外服務(wù)時的輸入輸出接口(入?yún)?出參),以及推理的代碼,確定了這二項后,在導(dǎo)入模型時,modelarts會用到。如下圖
那么config.json和推理代碼是長上面樣子的呢?
如下:config.json
{ "model_type": "TensorFlow", "runtime": "tf2.1-python3.7", "model_algorithm": "predict_analysis", "apis": [ { "protocol": "http", "url": "/", "method": "post", "request": { "Content-type": "application/json", "data": { "type": "object" "properties": { "input_x": {"type": "string"} }, "required": ["input_x"] } }, "response": { "Content-type": "application/json", "data": { "type": "object", "properties": { "result": {"type": "string"} }, "required": ["result"] } } }], }
推理代碼customize_service.py:
# -*- coding: utf-8 -*- from model_service.tfserving_model_service import TfServingBaseService import tensorflow.compat.v1 as tf tf.disable_eager_execution() class my_service(TfServingBaseService): def __init__(self, model_name, model_path): # these three parameters are no need to modify self.model_name = model_name self.model_path = model_path self.signature_key = 'test_signature' # add the input and output key of your pb model here, # these keys are defined when you save a pb file self.input_key_1 = 'input_x' self.output_key_1 = 'output' config = tf.ConfigProto(allow_soft_placement=True) with tf.get_default_graph().as_default(): self.sess = tf.Session(graph=tf.Graph(), config=config) meta_graph_def = tf.saved_model.loader.load(self.sess, ["igraphtag"], self.model_path) self.signature = meta_graph_def.signature_def # define input and out tensor of your model here input_images_tensor_name = self.signature[self.signature_key].inputs[self.input_key_1].name output_score_tensor_name = self.signature[self.signature_key].outputs[self.output_key_1].name self.input_images = self.sess.graph.get_tensor_by_name(input_images_tensor_name) self.output_score = self.sess.graph.get_tensor_by_name(output_score_tensor_name) print('^_^_init_ tensor in is',self.input_images) print('^_^_init_ tensor out is',self.output_score) def _inference(self, data): """ model inference function Here are a inference example of resnet, if you use another model, please modify this function """ print('^_^inference data is',data) img=data pred_score = self.sess.run(self.output_score, feed_dict={self.input_images: img}) result = {'result':str(pred_score)} return result def _preprocess(self, data): print('^_^pre data is ',data) preprocessed_data = data return preprocessed_data def _postprocess(self, data): print('^_^post data is ',data) infer_output = data return infer_output
注:這里的代碼參考了垃圾分類,可以從這里下載
要按照modelarts的模型包規(guī)范,寫好apis的json配置文件,和推理的代碼。參考文檔:模型包規(guī)范介紹
推理的代碼,是用來做對外服務(wù)的業(yè)務(wù)處理。部署為服務(wù)后,可以對外提供restful風格的http服務(wù),這樣你的服務(wù)可以以大家喜聞樂見的方式提供給大眾來調(diào)用。
config.json就是用來定義服務(wù)的輸入輸出接口。
推理的思路很簡單,和算法思路的最后一部分,保存模型的對應(yīng)起來的。要注意的是不要對差了,否則錯一小點又要重來。
1.加載模型,并按約定提取出用于輸入輸出的張量。
2.建立會話運行模型里的預(yù)測功能,獲取預(yù)測結(jié)果
3.組織返回
再然后,模型導(dǎo)入成功了,下面就是部署。部署就是準備環(huán)境、拉鏡像image、然后啟動。雖然是很小的模型,但是架子很大,所以還是比較慢,要幾分鐘。
部署沒什么好說的,就是免費規(guī)格排隊很慢,可能很久都排不到,可以用收費的,用完了記得停止服務(wù)。
服務(wù)啟動成功后,來測試一下服務(wù),看服務(wù)返回是不是正確,如果不正確,報錯什么的,要去看日志排查具體原因,找到原因修改后,再從導(dǎo)入模型來過~
有點奇怪的時,輸入接口咋不能輸入json格式的數(shù)據(jù)呢?
AI開發(fā)平臺ModelArts 機器學(xué)習(xí)
版權(quán)聲明:本文內(nèi)容由網(wǎng)絡(luò)用戶投稿,版權(quán)歸原作者所有,本站不擁有其著作權(quán),亦不承擔相應(yīng)法律責任。如果您發(fā)現(xiàn)本站中有涉嫌抄襲或描述失實的內(nèi)容,請聯(lián)系我們jiasou666@gmail.com 處理,核實后本網(wǎng)站將在24小時內(nèi)刪除侵權(quán)內(nèi)容。
版權(quán)聲明:本文內(nèi)容由網(wǎng)絡(luò)用戶投稿,版權(quán)歸原作者所有,本站不擁有其著作權(quán),亦不承擔相應(yīng)法律責任。如果您發(fā)現(xiàn)本站中有涉嫌抄襲或描述失實的內(nèi)容,請聯(lián)系我們jiasou666@gmail.com 處理,核實后本網(wǎng)站將在24小時內(nèi)刪除侵權(quán)內(nèi)容。