深度学习模型部署技术方案

  • 训练好的深度学习模型如何进行部署的相关技术方案
    • 1 什么是模型部署?
    • 2 数据科学项目整个开发流程
    • 3 使用flask 将 Keras深度学习模型部署为Web应用程序
    • 4 TensorFlow Serving + Docker + Tornado机器学习模型生产级快速部署
    • 5 使用tensorflow serving部署keras模型(tensorflow 2.0.0)
    • 6 Nvidia的TensorRT Inference Server
    • 7 Clipper的架构
    • 8 tensorflow serving 服务部署与访问(Python + Java)
    • 其他企业级AI开发平台

训练好的深度学习模型如何进行部署的相关技术方案

1 什么是模型部署?

在典型的机器学习和深度学习项目中,我们通常从定义问题陈述开始,然后是数据收集和准备、数据理解和模型构建,对吧?
但是,最后,我们希望我们的模型能够提供给最终用户,以便他们能够利用它。模型部署是任何机器学习项目的最后阶段之一,可能有点棘手。如何将机器学习模型传递给客户/利益相关者?模型的部署大致分为以下三个步骤:

  1. 模型持久化
    持久化,通俗得讲,就是临时数据(比如内存中的数据,是不能永久保存的)持久化为持久数据(比如持久化至数据库中,能够长久保存)。那我们训练好的模型一般都是存储在内存中,这个时候就需要用到持久化方式,在 Python 中,常用的模型持久化方式一般都是以文件的方式持久化。

  2. 选择适合的服务器加载已经持久化的模型

  3. 提高服务接口,拉通前后端数据交流

2 数据科学项目整个开发流程


图的过程是一个数据科学项目所要经历的典型的过程。从数据采集开始,经历数据分析,数据变形,数据验证,数据拆分,训练,模型创建,模型验证,大规模训练,模型发布,到提供服务,监控和日志。诸多的机器学习工具如Scikt-Learn,Spark, Tensorflow, MXnet, PyTorch提供给数据科学家们不同的选择,同时也给模型的部署带来了不同的挑战。利用不同的开源框架进行构建训练的模型在部署时有着不同的方式。

3 使用flask 将 Keras深度学习模型部署为Web应用程序


组成部分
客户端: 工作流中的客户端可以是任何设备或第三方应用,用于向托管用于模型预测的架构的服务器发送请求。比如:Facebook 会在新上传的图像中尝试标记出你的脸部。
负载均衡器: 负载均衡器用于通过集群中的多个服务器或实例将工作负载(请求)进行分布,目的是避免任何单一资源发生过载,进而将响应时间最小化、程序吞吐量最大化。在上图中,负载均衡器是面向公众的实体,会将来自客户端的所有请求分布到集群中的多台 Ubuntu 服务器上。
Nginx: Nginx 是一个开源网络服务器,但也可以用作负载均衡器,其以高性能和很小的内存占用而著称。它可以大量生成工作进程,每个进程能处理数千个网络连接,因而在极重的网络负载下也能高效工作。在上图中,Nginx 是某个服务器或实例的本地均衡器,用于处理来自公共负载均衡器的所有请求。我们也可以用 Apache HTTP Server 代替 Nginx。
Gunicorn: 这是一个 Python WSGI HTTP 服务器,移植自 Ruby 的 Unicorn 项目。它是 pre-fork worker 模式,意味着一个主线程会创建多个称为 worker 的子进程来处理请求。由于 Python 并非多线程,所以我们尝试创建多个 gunicorn worker,它们为单独进程且有各自的内存配置,以此来实现并行处理请求。Gunicorn 适用多种 Python 框架,我们也可以用 uWSGI 代替它。
Flask: 一款用 Python 编写的微型 web 框架,可以帮我们开发响应请求的 API 或 web 应用。Flask 也是一个 Python 编写的 Web 微框架,可以让我们使用 Python 语言快速实现一个网站或 Web 服务。并使用方式和 Bottle 相似,Flask 依赖 Jinja2 模板和 Werkzeug WSGI 服务。Werkzeug 本质是 Socket 服务端,其用于接收 HTTP 请求并对请求进行预处理,然后触发 Flask 框架,开发人员基于 Flask 框架提供的功能对请求进行相应的处理,并返回给用户,如果返回给用户的内容比较复杂时,需要借助 Jinja2 模板来实现对模板的处理,即将模板和数据进行渲染,将渲染后的字符串返回给用户浏览器。
Keras: 由 Python 编写的开源神经网络库,能够在 TensorFlow、CNTK 或 MXNet 上运行。Keras 也有一些替代选择:TensorFlow、Caffe、CNTK、PyTorch、MXNet、Chainer 和 Theano。

参考实例:
1 https://www.liangzl.com/get-article-detail-194875.html
2 https://www.jianshu.com/p/fb4c56cec3d6
3 http://www.atyun.com/32862.html
4 https://zhuanlan.zhihu.com/p/34610834、
实例代码:
https://github.com/mtobeiyf/keras-flask-deploy-webapp

RNN实例代码:https://github.com/WillKoehrsen/recurrent-neural-networks

优点:部署简单,可以快速上手,适用于demo展示

缺点:需要在服务器端安装所有依赖,多条并发请求需要启动做个线程推进,不同的模型需要启动不同的服务。

4 TensorFlow Serving + Docker + Tornado机器学习模型生产级快速部署


一、简介
当我们训练完一个tensorflow(或keras)模型后,需要把它做成一个服务,让使用者通过某种方式来调用你的模型,而不是直接运行你的代码(因为你的使用者不一定懂怎样安装),这个过程需要把模型部署到服务器上。常用的做法如使用flask、Django、tornado等web框架创建一个服务器app,这个app在启动后就会一直挂在后台,然后等待用户使用客户端POST一个请求上来(例如上传了一张图片的url),app检测到有请求,就会下载这个url的图片,接着调用你的模型,得到推理结果后以json的格式把结果返回给用户。
这个做法对于简单部署来说代码量不多,对于不熟悉web框架的朋友来说随便套用一个模板就能写出来,但是也会有一些明显的缺点:

  1. 需要在服务器上重新安装项目所需的所有依赖。
  2. 当接收到并发请求的时候,服务器可能要后台启动多个进程进行推理,造成资源紧缺。
  3. 不同的模型需要启动不同的服务

而为了解决第一个问题,Docker是最好的方案。这里举一个不是十分准确但是能帮助理解的例子:Docker在直觉上可以理解成为码头上的“集装箱”,我们把计算机系统比喻成码头,把应用程序比喻成码头上的货物,当集装箱还未被发明的时候,货物在码头上到处乱放,当要挑选某些货物的时候(执行程序),工人们到处乱找彼此干扰(依赖冲突),影响效率。如果把货物装在一个个集装箱里面,那么每个集装箱里面的货物整理就不会影响到其它集装箱。

Docker有两个重要概念,分别是image(镜像)和container(容器)。image可以理解成python中的类,container就是类的一个instance(实例)。我们把image pull到本地后,在这个image中启动一个container,然后我们就可以进入这个container里面做我们想做的事,例如配置环境,存放文件等等,这个过程可以形象地理解成我们买了一台新电脑,然后打开电脑装软件。

针对第二个问题,对于使用tensorflow、keras框架进行算法开发的用户来说,TensorFlow Serving能够很简单的把你的模型挂在服务器后台,然后你只需要写一个客户端把请求发过去,它就会把运算后的结果返回给你。而TensorFlow Serving的最佳使用方式就是使用一个已经编译好TensorFlow Serving功能的docker,你所要做的只是简单的运行这个docker即可。(具体含义就是将模型以及模型的依赖环境都封装到一个docker之中)

TensorFlow Serving还支持同时挂载多个模型或者多个版本的模型,只需简单地指定模型名称即可调用相应的模型,无需多写几份代码、运行多个后台服务。因此优势在于:

  1. 自动刷新使用新版本模型,无需重启服务。

  2. 无需写任何部署代码。

  3. 可以同时挂载多个模型。

二、导出你的模型
TensorFlow Serving只需要一个导出的tensorflow或keras模型文件,这个模型文件定义了整个模型的计算图,因此我们首先把一个训练好的模型进行导出。

如果模型的输出还不是最终的结果,需要进行其它运算,请尽可能把后处理的操作都用tf或者keras的API写进计算图的节点里面,尽量使模型的预测结果就是最终的结果,否则需要在web的代码中对返回的结果进行其它处理。

可以看到,TensorFlow Serving不需要其它环境依赖,只要tensorflow版本对了,导出的模型就能直接在TensorFlow Serving上使用,接收输入,返回输出,无需写任何部署代码。

三、Docker
1.安装docker
TensorFlow Serving的安装推荐使用docker,所以必须先安装docker。
2.安装nvidia-docker
3.拉取TensorFlow Serving镜像

四、运行TensorFlow Serving Docker
五、Client客户端
TensorFlow Serving启动后,我们需要用一个客户端来发送预测请求,跟以往请求不同的是,TensorFlow Serving使用的是gRPC协议,我们的客户端需要安装使用gRPC的API,以特定的方式进行请求以及接收结果。
六、Tornado Web服务
TensorFlow模型的计算图,一般输入的类型都是张量,你需要提前把你的图像、文本或者其它数据先进行预处理,转换成张量才能输入到模型当中。而一般来说,这个数据预处理过程不会写进计算图里面,因此当你想使用TensorFlow Serving的时候,需要在客户端上写一大堆数据预处理代码,然后把张量通过gRPC发送到serving,最后接收结果。现实情况是你不可能要求每一个用户都要写一大堆预处理和后处理代码,用户只需使用简单POST一个请求,然后接收最终结果即可。因此,这些预处理和后处理代码必须由一个“中间人”来处理,这个“中间人”就是Web服务。

我们使用Tornado框架来搭建我们的Web服务,Tornado是一个支持异步非阻塞的高性能Web框架,可以接收多个用户的并发请求,然后向TensorFlow Serving并发请求结果,并在其中承担所有的数据预处理、后处理任务。

详细的教程信息见:https://zhuanlan.zhihu.com/p/52096200

5 使用tensorflow serving部署keras模型(tensorflow 2.0.0)

1 导出Keras模型
keras模型训练完毕后,一般我们都会使用model.save(filepath)储存为h5文件,包含模型的结构和参数,而我们需要把这个h5文件导出为tensorflow serving所需要的模型格式:

from keras import backend as K
from keras.models import load_model
import tensorflow as tf# 首先使用tf.keras的load_model来导入模型h5文件
model_path = 'v7_resnet50_19-0.9068-0.8000.h5'
model = tf.keras.models.load_model(model_path, custom_objects=dependencies)
model.save('models/resnet/', save_format='tf')  # 导出tf格式的模型文件

注意,这里要使用tf.keras.models.load_model来导入模型,不能使用keras.models.load_model,只有tf.keras.models.load_model能导出成tfs所需的模型文件。
2 Docker部署模型
一律使用docker来部署你的模型,如果还不知道docker是什么,不知道怎么用docker来拉取tfs的镜像,请查阅这篇文章:
https://zhuanlan.zhihu.com/p/52096200
这里默认你已经会拉取tfs模型到本地,现在执行以下容器启动命令:

sudo nvidia-docker run -p 8500:8500 \-v /home/projects/resnet/weights/:/models \--name resnet50 \-itd --entrypoint=tensorflow_model_server tensorflow/serving:2.0.0-gpu \--port=8500 --per_process_gpu_memory_fraction=0.5 \--enable_batching=true --model_name=resnet --model_base_path=/models/season &

3 请求客户端
模型部署起来后,我们要写一个grpc客户端来请求模型,代码参考:

from tensorflow_serving.apis import predict_pb2
from tensorflow_serving.apis import prediction_service_pb2_grpc
import grpcdef request_server(img_resized, server_url):'''用于向TensorFlow Serving服务请求推理结果的函数。:param img_resized: 经过预处理的待推理图片数组,numpy array,shape:(h, w, 3):param server_url: TensorFlow Serving的地址加端口,str,如:'0.0.0.0:8500' :return: 模型返回的结果数组,numpy array'''# Request.channel = grpc.insecure_channel(server_url)stub = prediction_service_pb2_grpc.PredictionServiceStub(channel)request = predict_pb2.PredictRequest()request.model_spec.name = "resnet"  # 模型名称,启动容器命令的model_name参数request.model_spec.signature_name = "serving_default"  # 签名名称,刚才叫你记下来的# "input_1"是你导出模型时设置的输入名称,刚才叫你记下来的request.inputs["input_1"].CopyFrom(tf.make_tensor_proto(img_resized, shape=[1, ] + list(img_resized.shape)))response = stub.Predict(request, 5.0)  # 5 secs timeoutreturn np.asarray(response.outputs["fc2"].float_val) # fc2为输出名称,刚才叫你记下来的

tensorflow 2.0.0请使用以上这段代码,之前那篇tfs的部署文章里面的api已经变了。

我们测试一下,读取一张图片,发送请求到tfs:

from PIL import Image
import numpy as npimgpath = '20171101110450_48901.jpg'
x = Image.open(imgpath)
x = np.array(x).astype('float32')
x = (x - 128.) / 128.# grpc地址及端口,为你容器所在机器的ip + 容器启动命令里面设置的port
server_url = '0.0.0.0:8500'
request_server(x, server_url)

我们将会得到(我这里的resnet只输出4类多标签结果):

array([0.58116215, 0.04240507, 0.74790353, 0.1388033 ])

详细的文章内容:https://zhuanlan.zhihu.com/p/96917543

6 Nvidia的TensorRT Inference Server

如果你使用的是其它神经网络框架,例如caffe、pytorch,我会推荐Nvidia的TensorRT Inference Server,它支持所有模型的部署,包括TF系、ONNX系、mxnet等等,TRT会先对你的网络进行融合,合并可以同步计算的层,然后量化计算子图,让你的模型以float16、int8等精度进行推理,大大加速推理速度,而你只需要增加几行简单的代码就能实现。而且TRT Inference Server能够处理负载均衡,让你的GPU保持高利用率。

7 Clipper的架构

8 tensorflow serving 服务部署与访问(Python + Java)

我的目标是使用tensorflow serving 用docker部署模型后,将服务暴露出来,分别在Python和Java中对模型进行访问。
Tensorflow Serving 服务部署
我直接用tensorflow serving docker部署的,直接按照官方的文档即可,唯一可能不同的是国内的网络问题,可以将下载和安装的步骤从dockerfile里面转移到登陆docker container去手动做。
我的总体环境:
tensorflow 1.3.0
python 3.5
java 1.8
Tensorflow Serving 服务编写
这里我训练了一个分类器,主要有三个分类,主要代码如下:

#设置导出时的目录特征名
export_time = time.strftime('%Y-%m-%d-%H-%M-%S', time.localtime(time.time()))
#为了接收平铺开的图片数组(Java处理比较麻烦) 150528 = 224*224*3
x = tf.placeholder(tf.float32, [None, 150528])
x2 = tf.reshape(x, [-1, 224, 224, 3])
#我自己的网络预测
prob = net.network(x2)sess = tf.Session()
#恢复模型参数
saver = tf.train.Saver()
module_file = tf.train.latest_checkpoint(weights_path)
saver.restore(sess, module_file)
#获取top 1预测
values, indices = tf.nn.top_k(prob, 1)
#创建模型输出builder
builder = tf.saved_model.builder.SavedModelBuilder(exporter_path + export_time)
#转化tensor到模型支持的格式tensor_info,下面的reshape是因为只想输出单个结果数组,否则是二维的
tensor_info_x = tf.saved_model.utils.build_tensor_info(x)
tensor_info_pro = tf.saved_model.utils.build_tensor_info(tf.reshape(values, [1]))
tensor_info_classify = tf.saved_model.utils.build_tensor_info(tf.reshape(indices, [1]))
#定义方法名和输入输出
signature_def_map = {"predict_image": tf.saved_model.signature_def_utils.build_signature_def(inputs={"image": tensor_info_x},outputs={"pro": tensor_info_pro,"classify": tensor_info_classify},method_name=tf.saved_model.signature_constants.PREDICT_METHOD_NAME)}
builder.add_meta_graph_and_variables(sess,[tf.saved_model.tag_constants.SERVING],signature_def_map=signature_def_map)
builder.save()

可以使用python命令生成模型文件夹,里面包含了saved_model.pb文件和variables文件夹
接着在container中可以新建一个文件夹,如serving-models,在文件夹下新建该模型文件夹classify_data,用来存放的模型文件夹,使用docker拷贝的命令拷贝模型到模型文件夹中:

docker cp 本机模型文件夹 containerId:/serving-models/classify_data/模型版本号

启动模型服务,监听9000端口:

bazel-bin/tensorflow_serving/model_servers/tensorflow_model_server --port=9000 --model_name=classify_data --model_base_path=/serving-models/classify_data/

Python 客户端调用tensorflow serving 中的服务
而是用pip install tensorflow-serving-client安装了一个第三方提供的库来访问tensorflow serving服务,python代码如下:

import sys
sys.path.insert(0, "./")
from tensorflow_serving_client.protos import predict_pb2, prediction_service_pb2
import cv2
from grpc.beta import implementations
import tensorflow as tf
from tensorflow.python.framework import dtypes
import time#注意,如果在windows下测试,文件名可能需要写成:im_name = r"测试文件目录\文件名"
im_name = "测试文件目录/文件名"
if __name__ == '__main__':#文件读取和处理im = cv2.imread(im_name)re_im = cv2.resize(im, (224, 224), interpolation=cv2.INTER_CUBIC)#记个时start_time = time.time()#建立连接channel = implementations.insecure_channel("你的ip", 9000)stub = prediction_service_pb2.beta_create_PredictionService_stub(channel)request = predict_pb2.PredictRequest()#这里由保存和运行时定义,第一个是运行时配置的模型名,第二个是保存时输入的方法名request.model_spec.name = "classify_data"#入参参照入参定义request.inputs["image"].ParseFromString(tf.contrib.util.make_tensor_proto(re_im, dtype=dtypes.float32, shape=[1, 224, 224, 3]).SerializeToString())#第二个参数是最大等待时间,因为这里是block模式访问的response = stub.Predict(request, 10.0)results = {}for key in response.outputs:tensor_proto = response.outputs[key]nd_array = tf.contrib.util.make_ndarray(tensor_proto)results[key] = nd_arrayprint("cost %ss to predict: " % (time.time() - start_time))print(results["pro"])print(results["classify"])

最终输出,例如:

cost 5.115269899368286s to predict:
[ 1.]
[2]

Java 访问tensorflow中的服务
像我一样用第三方库,我是用的是这个http://mvnrepository.com/artifact/com.yesup.oss/tensorflow-client/1.4-2
在pom.xml下加入依赖:

        <dependency><groupId>com.yesup.oss</groupId><artifactId>tensorflow-client</artifactId><version>1.4-2</version></dependency><!-- 这个库是做图像处理的 --><dependency><groupId>net.coobird</groupId><artifactId>thumbnailator</artifactId><version>0.4.8</version></dependency><dependency><groupId>io.grpc</groupId><artifactId>grpc-netty</artifactId><version>1.7.0</version></dependency><dependency><groupId>io.netty</groupId><artifactId>netty-tcnative-boringssl-static</artifactId><version>2.0.7.Final</version></dependency>

Java代码:

String file = "文件地址"
//读取文件,强制修改图片大小,设置输出文件格式bmp(模型定义时输入数据是无编码的)
BufferedImage im = Thumbnails.of(file).forceSize(224, 224).outputFormat("bmp").asBufferedImage();
//转换图片到图片数组,匹配输入数据类型为Float
Raster raster = im.getData();
List<Float> floatList = new ArrayList<>();
float [] temp = new float[raster.getWidth() * raster.getHeight() * raster.getNumBands()];
float [] pixels  = raster.getPixels(0,0,raster.getWidth(),raster.getHeight(),temp);
for(float pixel: pixels) {floatList.add(pixel);
}#记个时
long t = System.currentTimeMillis();
#创建连接,注意usePlaintext设置为true表示用非SSL连接
ManagedChannel channel = ManagedChannelBuilder.forAddress("192.168.2.24", 9000).usePlaintext(true).build();
//这里还是先用block模式
PredictionServiceGrpc.PredictionServiceBlockingStub stub = PredictionServiceGrpc.newBlockingStub(channel);
//创建请求
Predict.PredictRequest.Builder predictRequestBuilder = Predict.PredictRequest.newBuilder();
//模型名称和模型方法名预设
Model.ModelSpec.Builder modelSpecBuilder = Model.ModelSpec.newBuilder();
modelSpecBuilder.setName("classify_data");
modelSpecBuilder.setSignatureName("predict_image");
predictRequestBuilder.setModelSpec(modelSpecBuilder);
//设置入参,访问默认是最新版本,如果需要特定版本可以使用tensorProtoBuilder.setVersionNumber方法
TensorProto.Builder tensorProtoBuilder = TensorProto.newBuilder();
tensorProtoBuilder.setDtype(DataType.DT_FLOAT);
TensorShapeProto.Builder tensorShapeBuilder = TensorShapeProto.newBuilder();
tensorShapeBuilder.addDim(TensorShapeProto.Dim.newBuilder().setSize(1));
#150528 = 224 * 224 * 3
tensorShapeBuilder.addDim(TensorShapeProto.Dim.newBuilder().setSize(150528));
tensorProtoBuilder.setTensorShape(tensorShapeBuilder.build());
tensorProtoBuilder.addAllFloatVal(floatList);
predictRequestBuilder.putInputs("image", tensorProtoBuilder.build());
//访问并获取结果
Predict.PredictResponse predictResponse = stub.predict(predictRequestBuilder.build());
System.out.println("classify is: " + predictResponse.getOutputsOrThrow("classify").getIntVal(0));
System.out.println("prob is: " + predictResponse.getOutputsOrThrow("pro").getFloatVal(0));
System.out.println("cost time: " + (System.currentTimeMillis() - t));

结果打印如下:

classify is: 2
prob is: 1.0
cost time: 6911

具体详细内容:https://blog.csdn.net/shin627077/article/details/78592729
https://blog.csdn.net/luoyexuge/article/details/79826141?utm_medium=distribute.pc_relevant.none-task-blog-baidujs-2
https://blog.csdn.net/qq_41375318/article/details/107253654

其他企业级AI开发平台

  1. 腾讯 Angel平台
  2. 华为Mindspore
  3. 海康威视 Hikflow
  4. 用于Java的DeepLearning4j
  5. 知乎的Jeeves

深度学习模型部署技术方案相关推荐

  1. 如何将深度学习模型部署到实际工程中?(分类+检测+分割)

    应用背景介绍 早在遥远的1989年,一家叫做ALVIVN的公司首次将神经网络用在汽车上,进行车道线检测和地面分割.时至今日,深度学习已经应用在自动驾驶系统的多个分支领域.首先是感知领域,常用的传感器有 ...

  2. 基于TensorRT的深度学习模型部署实战教程!

    应用背景介绍 早在遥远的1989年,一家叫做ALVIVN的公司首次将神经网络用在汽车上,进行车道线检测和地面分割.时至今日,深度学习已经应用在自动驾驶系统的多个分支领域.首先是感知领域,常用的传感器有 ...

  3. 基于web端和C++的两种深度学习模型部署方式

    深度学习Author:louwillMachine Learning Lab 本文对深度学习两种模型部署方式进行总结和梳理.一种是基于web服务端的模型部署,一种是基... 深度学习 Author:l ...

  4. 深度学习模型部署简要介绍

    一.模型部署简介 近几年来,随着算力的不断提升和数据的不断增长,深度学习算法有了长足的发展.深度学习算法也越来越多的应用在各个领域中,比如图像处理在安防领域和自动驾驶领域的应用,再比如语音处理和自然语 ...

  5. 【深度学习】基于web端和C++的两种深度学习模型部署方式

    深度学习 Author:louwill Machine Learning Lab 本文对深度学习两种模型部署方式进行总结和梳理.一种是基于web服务端的模型部署,一种是基于C++软件集成的方式进行部署 ...

  6. pytorch基于web端和C++的两种深度学习模型部署方式

    本文对深度学习两种模型部署方式进行总结和梳理.一种是基于web服务端的模型部署,一种是基于C++软件集成的方式进行部署. 基于web服务端的模型部署,主要是通过REST API的形式来提供接口方便调用 ...

  7. 为什么将表格的method改为post后就无法工作_用Python将Keras深度学习模型部署为Web应用程序...

    构建一个很棒的机器学习项目是一回事,但归根结底,你希望其他人能够看到你的辛勤工作.当然,你可以将整个项目放在GitHub上,但是怎么让你的祖父母也看到呢?我们想要的是将深度学习模型部署为世界上任何人都 ...

  8. 基于web端的深度学习模型部署

    1.1 web服务与技术框架 下面以ResNet50预训练模型为例,旨在展示一个轻量级的深度学习模型部署,写一个较为简单的图像分类的REST API.主要技术框架为Keras+Flask+Redis. ...

  9. 面向生产环境!深度学习模型部署资源全辑

    点上方计算机视觉联盟获取更多干货 仅作学术分享,不代表本公众号立场,侵权联系删除 转载于:机器学习实验室   Author:louwill Machine Learning Lab AI博士笔记系列推 ...

最新文章

  1. J2EE学习中一些值得研究的开源项目
  2. centos7安装mysql,安装easy install、pip、scrapy等
  3. 3分钟学会python_3分钟学会一个Python小技巧
  4. Vimdiff---VIM的比较和合并工具
  5. 【javascript】DOM操作方法(3)——document节点属性
  6. 简述工业机器人示教再现的一般步骤_基于激光焊缝跟踪传感器的工业机器人焊缝跟踪系统的应用焊接寻位...
  7. LUNA16_Challange数据预处理1
  8. 《C++沉思录 第2版》
  9. 魔鬼一样的二分查找模板
  10. dao获取到mysql存储函数_GreenDao3.0使用
  11. log4j2自定义级别日志
  12. 用C语言开发NES游戏(CC65) 准备工作
  13. PowerDesigner 15 License Key失效的解决方案
  14. Myeclipse10怎么找到 Servers
  15. android自适应屏幕方向,Android 屏幕自适应方向尺寸与分辨率-Fun言
  16. 唯独发奋,努力,勤奋做事才是唯一的出路 C#-患者实体类
  17. java有substr方法_java substring和substr
  18. 微信公众号拉取扫码功能
  19. 如何将枯燥的大数据变得生动有趣!
  20. PAT L3-011 直捣黄龙

热门文章

  1. matlab计算铰接式履带车辆转向性能
  2. Amazon面试体验分享2020年SDE-1(全职推荐)
  3. ISO26262:功能安全解决了什么问题?
  4. Android任务栈的理解
  5. 关于SQL 与 NoSQL的区别
  6. TensorFlow常用激活函数及其特点用法(6种)详解
  7. vmware 虚拟机启动失败, Intel VT-x 处于禁用状态
  8. Python使用matplotlib可视化哑铃图、强调从一个点到另一个点的变化、数量的变化、客户满意度的变化等(Dumbbell Plot)
  9. Java生成指定范围的随机数
  10. 十大人文科技类图书(转)