大家好,感谢邀请,今天来为大家分享一下函数计算部署机器学习遇到的问题及解决方案的问题,以及和的一些困惑,大家要是还不太明白的话,也没有关系,因为接下来将为大家分享,希望可以帮助到大家,解决大家的问题,下面就开始吧!
今天我们来看看如何将机器学习应用迁移到函数计算。
1. 本地开发
首先,我们来看看本地开发机器学习应用程序的步骤。我们大概可以将本地开发概括为三个步骤,即编写代码、安装依赖、运行调试。让我们分别看一下。
1.1 代码编写
假设我们的项目结构是:
项目根index.pymodel_data检查点model.data-00000-of-00001model.indexmodel.metpic e2.jpg 其中index.py存放机器学习相关代码,model_data存放数据模型,pic存放待测试的图片。
index.py的内容为(代码参考本文):
# -*-coding:utf-8 -*- import osimport sysimport cv2 import numpy as npimport tensorflow as tf saver=NonedefversePic(src): for i in range(src.shape[0]): for j in range(src.shape [1]): src[i, j]=255 - src[i, j] return src def main(): sess=tf.Session() saver=tf.train.import_meta_graph('model_data/model.meta') saver.restore(sess, 'model_data/model') graph=tf.get_default_graph() input_x=sess.graph.get_tensor_by_name('Mul:0') y_conv2=sess.graph.get_tensor_by_name('final_result:0') path='pic/e2. jpg' im=cv2.imread(path, cv2.IMREAD_GRAYSCALE) im=reversePic(im) im=cv2.resize(im, (28, 28), interpolation=cv2.INTER_CUBIC) x_img=np.reshape(im , [- 1 , 784]) output=sess.run(y_conv2 , feed_dict={input_x:x_img}) print '预测为%d' % (np.argmax(output)) sess.close()if __name__=='__main__': main ()
1.2 安装依赖
运行应用程序之前,需要安装应用程序所依赖的模块。这个主要依赖opencv和tensorflow。安装方法非常简单:
pip install opencv-pythonpip install tensorflow 执行这两个命令后,opencv-python和tensorflow将被安装在系统目录中。 Linux下的默认位置是/usr/local/lib/pythonX.Y/site-packages。
当
1.3 运行
运行时,python会自动在配置的路径中查找相关模块并加载。
$ python index.py预测为8 经过这三个步骤,我们就完成了本地机器学习应用的开发。让我们看看如何将应用程序迁移到函数计算。
2. 迁移函数计算
2.1 本地开发与函数计算开发对比
首先,我们需要做一些准备工作。我们思考一下函数计算应用程序的开发方法和本地应用程序的开发方法有什么区别?
代码输入。本地开发时,代码可以省略main函数,也可以提供main函数作为程序入口点。然而,在函数计算中,函数入口点是固定的。非Http触发器的函数入口点必须是包含两个参数的函数,例如:def handler(event, context)。模块依赖关系。在本地开发时,项目所依赖的模块通常会安装到系统的某个目录下。比如我们上面执行了pip install tensorflow。对于函数计算来说,为了最大程度地优化应用,向用户开放的操作空间通常比较小。因此,对于函数计算来说,目前还无法将项目依赖安装到运行环境中。我们只能将自定义模块打包在一起。参考。跑步。本地开发时,需要使用python命令或者IDE来运行代码。在函数计算中,我们需要首先将应用程序部署到函数计算中,然后通过触发器或控制台手动触发执行。接下来我们将根据这三种开发方式的差异来改造代码。
2.2 改造代码
2.2.1 代码入口改造
这个比较简单,你只需要
def main(): 修改为
def handler(event, context): 并删除以下代码:
if __name__=='__main__': main()
2.2.2. 模块依赖
这个稍微复杂一点。不同的语言由于模块加载机制不同,这里的处理逻辑也不同。比如java,无论你使用maven还是gradle,都可以轻松的一键将代码和依赖打包成jar。但遗憾的是python目前还没有这样的机制。
我们先根据场景对python依赖的模块做一个简单的分类。
应用依赖:对于本例中使用pip安装的模块,例如pip install tensorflow,我们暂时将其称为应用依赖。
系统依赖:在某些场景下,python安装的库只是底层c和c++库调用的封装。例如,使用zbar时,除了使用pip install zbar之外,系统中还必须安装相应的库:apt-get install -y libzbar-dev。现在,我们将像libzbar-dev 这样需要使用系统包管理器安装的库称为系统依赖项。
资源依赖:对于一些应用,比如机器学习,启动后需要加载数据模型。数据模型需要在程序启动时准备好。我们暂时将这种依赖称为资源依赖。资源依赖性是特殊的。它们是我们的应用程序逻辑所需要的,并且通常尺寸相对较大。
对于应用程序依赖,我们可以通过pip的-t参数更改其安装位置,例如pip install -t $(pwd) tensorflow。并且可以通过sys.path更改加载行为,以便可以从指定目录加载模块。
对于系统依赖,我们可以通过apt-get下载deb包,然后使用deb包安装到指定目录中。
apt-get install -y -d -o=dir:cache=$(pwd) libzbar-devfor f in $(ls $(pwd)/archives/*deb);执行dpkg -x $f $(pwd); dorm -r 对于系统依赖项中包含的链接库,存档可以通过LD_LIBRARY_PATH 变量更改其加载行为。
对于资源依赖,因为控制在我们的代码中,所以我们只需要改变代码的处理逻辑即可。
根据上面的描述,我们可以整理成下表:
类别定义安装方法示例指定位置安装方法示例影响加载的因素应用程序依赖pip 安装的模块pip install tensorflow pip install -t $(pwd) tensorflow sys.path 系统依赖系统包管理器安装的依赖apt-get install - y libzbar- dev apt-get install -y -d -o=dir:cache=$(pwd) libzbar-dev
for f in $(ls $(pwd)/archives/*deb);执行dpkg -x $f $(pwd);完毕
rm -r archives LD_LIBRARY_PATH 资源依赖 代码依赖的资源,比如数据模型 \ \ 由应用代码控制 2.2.3 下载依赖的逻辑
对于我们的演示应用程序,有两种依赖关系,一种是应用程序依赖,另一种是资源依赖。我们唯一需要特别处理的是应用程序依赖性。我们需要在项目目录中创建一个名为applib的目录,并将应用程序依赖项下载到该目录中。这里需要注意的是,如果引用的模块使用的是C/C++/go编译的可执行文件或者库文件,建议使用fcli的sbox来下载。使用方法是:
mkdir applib fcli shellsbox -d applib -t python2.7pip install -t $(pwd) tensorflowpip install -t $(pwd) 执行opencv-python后,你会发现applib包含了项目所需的应用程序依赖项。
2.2.4 打包依赖上传到 OSS
机器学习的应用依赖和资源依赖通常都比较大,很容易超出函数计算的代码包(50M)的限制。为了避免这个问题,我们需要将这些依赖上传到OSS:
cd applib zip -r applib.zip * mv applib.zip ./; cd . 执行后,项目会多一个压缩包,名为applib.zip,可以上传到oss。
同样,对资源依赖项执行相同的操作:
cd model_data zip -r model_data.zip * mv model_data.zip ./; cd .
2.2.5 初始化依赖
这里提供一个模板代码,负责首次启动时从OSS下载资源到本地、解压、配置功能。做好相应的环境变量。我们可以在项目中创建一个名为loader.py的文件,内容如下:
# -*-coding:utf-8 -*-导入sysimport zipfileimport osimport oss2import导入时间app_lib_object=os.environ['AppLibObject']app_lib_dir=os.environ['AppLibDir']model_object=os.environ['ModelObject']model_dir=os.environ['AppLibObject']app_lib_dir=os.environ['AppLibObject'] environ['ModelDir']local=bool(os.getenv('local', ''))print '本地运行:' + str(local)inilized=Falsedef download_and_unzip_if_not_exist(objectKey, path, context): creds=context.credentials if (local): print '感谢您在本地运行函数!' auth=oss2.Auth(creds.access_key_id, creds.access_key_secret) else: auth=oss2.StsAuth(creds.access_key_id, creds.access_key_secret, creds .security_token) 端点=os.environ['Endpoint'] 桶=os.environ[' Bucket'] print 'objectKey:' + objectKey print 'path:' + 路径print 'endpoint:' + 端点print 'bucket:' + 桶bucket=oss2 .Bucket(auth, 端点, Bucket) zipName='/tmp/tmp.zip' print '下载前' + objectKey + ' .' start_download_time=time.time() bucket.get_object_to_file(objectKey, zipName) print '下载后,用了%s 秒.' % (time.time() - start_download_time)如果不是os.path.exists(path): os.mkdir(path) print '解压缩前' + objectKey + ' .' start_unzip_time=time.time() with zipfile.ZipFile(zipName, 'r') as z: z.extractall(path) print '解压完成,用了%s 秒.' % (time.time() - start_unzip_time)def handler(event, context): 如果没有inilized 则全局inilized: if (非本地): download_and_unzip_if_not_exist( app_lib_object, app_lib_dir, context) download_and_unzip_if_not_exist(model_object, model_dir, context) sys.path.insert(1, app_lib_dir) print sys.path inilized=True file_handle, desc=None, None fn, modulePath, desc=imp.find_module('index ') mod=imp.load_module('index', fn, modulePath, desc) request_handler=getattr(mod, 'handler') return request_handler(event, context) 这段代码首先会读取AppLibObject环境变量,从OSS下载应用依赖并将它们解压到AppLibDir 环境变量表示的目录中。
其次,读取ModelObject环境变量,用于从OSS下载资源依赖,并解压到ModelDir环境变量代表的目录。
最后,当依赖项准备就绪时,将调用index.py中的处理函数。
理论上,这段代码可以用于任何其他需要下载应用依赖和资源依赖的场景。我们的index.py中需要修改的就是将原来获取模型依赖的固定路径改为使用ModelDir获取路径。
2.3 本地运行调试
代码写完后,我们的目录结构调整为:
项目根目录代码index.pyloader.pypice2.jpgapplib. * model_data checkpoint model.data-00000-of-00001 model.index model.met 我们本地运行一下看看效果。这里我们使用函数计算推出的fc-dcoker工具。
为了避免每次本地调试都进行不必要的下载,我们采取了技巧,将应用程序依赖和资源依赖挂载到fc-docker中,并打开本地标志:
docker run --rm \ -e local=true \ -e AppLibObject=applib.zip \ -e AppLibDir=/tmp/applib \ -e ModelObject=model_data.zip \ -e ModelDir=/tmp/model \ -v $( pwd)/code:/code \ -v $(pwd)/applib:/tmp/applib \ -v $(pwd)/model_data:/tmp/model \ aliyunfc/runtime-python2.7 \ loader.handler 得到结果:
2018-08-28 17:44:16.043564: I tensorflow/core/platform/cpu_feature_guard.cc:141]您的CPU支持此TensorFlow二进制文件未编译为使用的指令: AVX2 FMAFunctionCompute python运行时inited.FC Invoke Start RequestId: f3ea930e-d7 e2-4173-9726-453cdd89f18c本地运行: True ['/code', '/tmp/applib', '/var/fc/runtime/python2.7/src', '/usr/local/lib/python27.zip', '/usr/local/lib/python2 .7', '/usr/local/lib/python2.7/plat-linux2', '/usr/local/lib/python2.7/lib-tk', '/usr/local/lib/python2.7 /lib-old', '/usr/local/lib/python2.7/lib-dynload', '/usr/local/lib/python2.7/site-packages']2018-08-28T17:44:16.154Z f3ea930e-d7e2 - 4173-9726-453cdd89f18c [INFO] 从/tmp/model/model 恢复参数预测为8RequestId: f3ea930e-d7e2-4173-9726-453cdd89f18c 计费持续时间: 9954 ms 内存大小: 1998 MB 最大使用内存333 60 239 MB
2.4 部署
本地开发已完成、连接接下来,我们需要在线部署应用程序。这里我们使用函数计算推出的Fun工具。
Fun工具的使用步骤如下:
进入发布页面找到对应平台的二进制版本,解压即可使用。或者使用npm install @alicloud/fun -g 也可以直接使用。使用fun config配置ak、region等信息。编写template.ymlfun部署部署。是的,您不需要登录控制台进行繁琐的配置。你只需要在项目下提供一个template.yml:
ROSTemplateFormatVersion: '2015-09-01'Transform: 'Aliyun:Serverless-2018-04-03'Resources: tensorflow: # 服务名称Type: 'Aliyun:Serverless:Service' Properties3336 0 描述第:章/code/Description: '张量流应用程序!' Runtime: python2.7 MemorySize: 1024 Timeout: 300 EnvironmentVariables: Bucket: just-fc-test # 替换为自己的oss Bucket Endpoint: 'https://oss-cn-shanghai-internal.aliyuncs.com' # 替换OSS Endpoint AppLibObject: applib.zip AppLibDir3第3360章model_data.zip ModelDir: /tmp/model 此时,我们的项目中有另一个template.yml,其结构
项目根目录代码index.pyloader.pypice2.jpgapplib*template.yml model_data checkpoint model.data-00000-of-00001 model.index model.met 通过这个template.yml,可以在执行fun deploy后创建相应的服务和功能。并配置函数的环境变量。
$ fun deploy等待部署服务tensorflow.等待部署功能测试.等待打包功能测试代码.打包功能测试代码完成功能测试部署成功服务tensorflow部署成功即使代码被修改,只需重复执行有趣的部署即可。
接下来,打开https://fc.console.aliyun.com/控制台,依次找到创建的服务和函数,点击执行,即可得到与本地一致的输出:
2.5 补充
在上面的示例中,我们只列出了应用程序依赖项和资源依赖项。系统依赖的处理逻辑比较简单。例如,我们以zbar为例。除了在applib中通过pip安装zbar之外,还需要在代码目录下新建lib目录,并通过沙箱在该目录下执行:
apt-get install -y -d -o=dir:cache=$(pwd) libzbar-devfor f in $(ls $(pwd)/archives/*deb);执行dpkg -x $f $(pwd); dorm -r 归档文件执行完成后,目录结构变为:
项目根 code lib usr/lib *如上所述,我们需要修改LD_LIBRARY_PATH来改变系统依赖的加载行为,所以我们需要使用模板。在yaml 中的EnvironmentVariables 下添加一行:
LD_LIBRARY_PATH: /code/lib/usr/lib:/code:/code/lib:/usr/local/lib 此时就可以在index.py等文件中直接使用zbar了。
用户评论
函数计算部署机器学习模型感觉挺爽的,不用担心基础设施管理!不过遇到过一次数据类型转换的问题,搞得我一头雾水啊。好在博客里提供的例子帮我解决了。希望以后能看到更多针对不同场景的案例分享。
有8位网友表示赞同!
这个标题简直戳中我的痛点!我也经常在函数计算部署模型时遇到问题,比如代码调试太卡,运行效率也比较低。希望能找到一些更优化的解决方案!
有9位网友表示赞同!
函数计算确实方便快捷,但是对于复杂的机器学习模型来说,它的资源限制可能让人头疼。例如我的项目需要很大的内存和GPU支持,在函数计算平台上部署就显得力不从心了。
有5位网友表示赞同!
讲真,部署机器学习模型还是比较费力的,特别是面对不同的平台和环境。这篇博文提供的解决方案挺实用的,可以帮助开发者快速上手,解决一些常见问题。
有19位网友表示赞同!
数据类型的转换确实是个大坑!函数计算平台的数据结构和传统框架不同,需要特别注意一下。这个博文总结得很详细,给我带来了很多启发。希望以后能多关注一些更具体的应用场景分析
有16位网友表示赞同!
作为一名机器学习爱好者,我最近也开始尝试用函数计算来部署模型。这篇博文给了我很大的帮助!特别是对于数据格式转换的解释,让我豁然开朗。これからも積極的に学ぶことを続けていきたいと思います!
有18位网友表示赞同!
虽然函数计算确实方便快捷,但是我觉得它并不是万能的。对于一些需要高并发处理能力的机器学习应用来说,还是更适合在云服务器上部署比较好。
有17位网友表示赞同!
我对函数计算平台的使用经验还不太丰富,所以这篇博文对我的帮助很大!希望能了解更多关于部署机器学习模型的最佳实践?
有9位网友表示赞同!
这个话题太赞了!函数计算的确给机器学习开发带来了很多便利,但同时也存在一些挑战。比如如何优化代码以提升执行效率呢?博主可以多分享一些经验吗?
有5位网友表示赞同!
虽然文章提到了一些常见问题和解决方案,但我还是觉得对函数计算环境的深入理解非常重要。还需要继续学习和实践才能真正掌握它的使用技巧吧!
有5位网友表示赞同!
机器学习模型部署上一直是我头疼的问题,功能计算平台看起来很有潜力,但需要花费更多的时间去学习和适应呢
有11位网友表示赞同!
数据流处理、模型训练加速等方面,函数计算平台有很大的发展空间。希望未来能够看到更成熟的解决方案!
有10位网友表示赞同!
函数计算的部署问题确实复杂一点,而且不同类型的模型也需要根据实际情况调整部署方案。这篇博文是一个很好的入门指南!
有8位网友表示赞同!
这篇文章把复杂的问题讲得通俗易懂,我很感激您的分享!希望未来能看到更多针对不同场景的案例分析,这样才能更好地指导我们的实践。
有6位网友表示赞同!
部署机器学习模型真是门技术活,函数计算平台虽然方便快捷,但需要不断学习和探索才能真正发挥它的优势!
有16位网友表示赞同!
对函数计算了解的不多,这篇博文让我对它的适用场景有了更清晰的认识。感谢您的详细解答!希望未来能看到更多关于它优化部署问题的探讨!
有14位网友表示赞同!
数据格式转换的确是比较头疼的问题,没想到函数计算平台上还有这么多解决方案可以参考。谢谢作者分享经验!
有11位网友表示赞同!
函数计算平台未来发展潜力巨大,相信在机器学习领域也会发挥越来越重要的作用!期待这个技术的进一步进步!
有5位网友表示赞同!
感觉函数计算的应用场景还比较单一,希望未来能够看到更多创新和突破,让机器学习部署更灵活便捷。
有15位网友表示赞同!