The author | Jiang Yu

preface

Image classification is a hot topic in the field of artificial intelligence. The popular explanation is an image processing method that distinguishes different categories of objects according to their different characteristics reflected in the image information.

It uses computer to make quantitative analysis of the image, and classifies the image or each pixel or region in the image into a certain kind of several categories, so as to replace human’s visual interpretation.

Image classification is also often encountered in actual production and life, and has a strong pertinence for different fields or needs. For example, through photographing flowers to identify flower information, through the comparison of human face information.

In general, these image recognition or classification tools are data collection on the client side and calculation on the server side to obtain results, that is to say, in general, there are special APIS to realize image recognition. For example, each major cloud vendor will provide us with similar capabilities for a fee:

Ali Cloud image recognition page:

Huawei Cloud image recognition page:

This article will use an interesting Python library to quickly build the image classification function on the cloud, and in conjunction with the API gateway, provide API functionality externally, and implement a Serverless architecture “image classification API” **.

First, I’ll introduce you to the required dependency library: ImageAI. From the official documentation for this dependency we can see the following description:

ImageAI is a Python library designed to enable developers to build applications and systems with deep learning and computer vision capabilities in a few simple lines of code. Based on the principle of simplicity, ImageAI supports state-of-the-art machine learning algorithms for image prediction, custom image prediction, object detection, video detection, video object tracking and image prediction training. ImageAI currently supports image prediction and training using four different machine learning algorithms trained on the Imagenet-1000 dataset. ImageAI also supports object detection, video detection, and object tracking using RetinaNet trained on COCO datasets. Ultimately, ImageAI will provide broader and more specialized support for computer vision, including but not limited to image recognition in special environments and special fields.

That is to say, this dependency library can help us complete basic image recognition and video target extraction. Although it provides some data sets and models, we can also carry out additional training and customized expansion according to our own needs. From the official code, we can see a simple Demo:

# -*- coding: Utf-8 -*- from imageai.Prediction Import ImagePrediction # prediction.setModelTypeAsResNet() prediction.setModelPath("resnet50_weights_tf_dim_ordering_tf_kernels.h5") prediction.loadModel() predictions, probabilities = prediction.predictImage("./picture.jpg", result_count=5 ) for eachPrediction, eachProbability in zip(predictions, probabilities): print(str(eachPrediction) + " : " + str(eachProbability))Copy the code

When we specify picture.jpg as:

Our results after implementation are as follows:

Laptop: 71.43893241882324 Notebook: 16.265612840652466 modem: 4.899394512176514 HARD_disc: The mouse 4.007557779550552:1.2981942854821682Copy the code

If the resNET50_weightS_TF_DIM_ORDERING_TF_kernel. h5 model is too large and time-consuming, you can select the following model as required:

  • SqueezeNet (file size: 4.82 MB, shortest prediction time, moderate accuracy)
  • ResNet50 by Microsoft Research (File size: 98 MB, fast prediction time, high accuracy)
  • InceptionV3 by Google Brain Team (File size: 91.6MB, slow prediction time, higher accuracy)
  • DenseNet121 by Facebook AI Research (file size: 31.6 MB, slow prediction time, highest accuracy)

Github address: github.com/OlafenwaMos…

Or refer to the ImageAI official documentation: imageai-cn.readthedocs. IO /zh_CN/lates…

Project Serverless,

Write the entry method and initialize the project according to the calculation requirements of the function. At the same time, create folder Model under the current project and copy the model file to this folder:

Overall project process:

Implementation code:

# -*- coding: utf-8 -*- from imageai.Prediction import ImagePrediction import json import uuid import base64 import random # Response class Response: def __init__(self, start_response, response, errorCode=None): self.start = start_response responseBody = { 'Error': {"Code": errorCode, "Message": response}, } if errorCode else { 'Response': ResponseBody ['ResponseId'] = STR (uuid.uuid1()) print(" response: ", json.dumps(responseBody)) self.response = json.dumps(responseBody) def __iter__(self): status = '200' response_headers = [('Content-type', 'application/json; charset=UTF-8')] self.start(status, Response_headers) yield self.response.encode("utf-8") # randomStr = lambda num=5: "".join(random.sample('abcdefghijklmnopqrstuvwxyz', Num) # model Load print (" Init model ") prediction = ImagePrediction () prediction. SetModelTypeAsResNet () print (" Load model ") prediction.setModelPath("/mnt/auto/model/resnet50_weights_tf_dim_ordering_tf_kernels.h5") prediction.loadModel() print("Load complete") def handler(environ, start_response): try: request_body_size = int(environ.get('CONTENT_LENGTH', 0)) except (ValueError): Request_body_size = 0 requestBody = json. Loads (environ['wsgi.input'].read(request_body_size).decode(" UTF-8 ")) # print("Get pucture") imageName = randomStr(10) imageData = base64.b64decode(requestBody["image"]) imagePath = "/tmp/" + ImageName with open(imagePath, 'WB ') as F: f. rite(imageData) # print("Predicting... ") result = {} predictions, probabilities = prediction.predictImage(imagePath, result_count=5) print(zip(predictions, probabilities)) for eachPrediction, eachProbability in zip(predictions, probabilities): result[str(eachPrediction)] = str(eachProbability) return Response(start_response, result)Copy the code

Required dependencies:

Tensorflow ==1.13.1 numpy==1.19.4 scipy==1.5.4 Opencv-Python ==4.4.0.46 Pillow ==8.0.1 matplotlib==3.3.3 H5PY ==3.1.0 Keras = = 2.4.3 imageai = = 2.1.5Copy the code

Write the configuration files required for deployment:

ServerlessBookImageAIDemo: Component: fc Provider: alibaba Access: release Properties: Region: cn-beijing Service: Name: ServerlessBook Description: ServerlessBook Case Log: Auto Nas: Auto Function: Name: serverless_imageAI Description: CodeUri: Src:./ Src Excludes: -src /. Fun-src/Model Handler: index. Handler Environment: -key: PYTHONUSERBASE Value: /mnt/auto/.fun/python MemorySize: 3072 Runtime: python3 Timeout: 60 Triggers: - Name: ImageAI Type: HTTP Parameters: AuthType: ANONYMOUS Methods: - GET - POST - PUT Domains: - Domain: AutoCopy the code

In the code and configuration, you can see the existence of directory: / MNT /auto/. This part is actually the address after the NAS is mounted, so you only need to write it into the code in advance. The next step will be to create the NAS and configure the mount point.

Project deployment and testing

After completing the above steps, you can:

s deploy
Copy the code

Deploy the project. After deployment, you can see the following results:

After deployment is complete, you can use:

s install docker
Copy the code

To install dependencies:

After the dependencies are installed, you can see the.fun directory generated under the directory. This directory is the dependencies packaged by docker. These dependencies are the dependencies declared in the requirements.txt file.

After that, we go through:

s nas sync ./src/.fun
Copy the code

Package the dependent directory and upload it to nas, and then package the model directory and upload it:

s nas sync ./src/model
Copy the code

This can be done by:

s nas ls --all
Copy the code

To view directory details:

Once done, we can write a script to test the same as the test image, using code:

import json
import urllib.request
import base64
import time

with open("picture.jpg", 'rb') as f:
    data = base64.b64encode(f.read()).decode()

url = 'http://35685264-1295939377467795.test.functioncompute.com/'

timeStart = time.time()
print(urllib.request.urlopen(urllib.request.Request(
    url=url,
    data=json.dumps({'image': data}).encode("utf-8")
)).read().decode("utf-8"))
print("Time: ", time.time() - timeStart)
Copy the code

You can see the result:

{"Response": {"laptop": "71.43893837928772", "notebook": "16.265614330768585", "modem": "4.899385944008827", "hard_disc": "4.007565602660179", "mouse": "1.2981869280338287"}, "ResponseId": "1 d74ae7e eb - 298 - a - 11-0701 8374-02421500"} Time: 29.16020894050598Copy the code

As you can see, the calculation of the function returns the expected result smoothly, but the overall time is more than expected, nearly 30 seconds. At this point, we run the test script again:

{"Response": {"laptop": "71.43893837928772", "notebook": "16.265614330768585", "modem": "4.899385944008827", "hard_disc": "4.007565602660179", "mouse": "1.2981869280338287"}, "ResponseId": "4 b8be48a eb - 298 - a - 11 - ba97-024215000501"} Time: 1.1511380672454834Copy the code

As you can see, the execution time again is only 1.15 seconds, a full 28 seconds improvement over the last time.

Project optimization

In the last round of testing, we can see that the time difference between the first startup and the second startup of the project is mainly due to the extremely long time wasted by the function when loading the model.

Even locally, we can simply test:

# -*- coding: Utf-8 -* -import time timeStart = time.time() # Model loading from imageai.Prediction import ImagePrediction = utF-8 -* -import time timeStart = time.time() # Model loading from imageai.Prediction import ImagePrediction = ImagePrediction() prediction.setModelTypeAsResNet() prediction.setModelPath("resnet50_weights_tf_dim_ordering_tf_kernels.h5") prediction.loadModel() print("Load Time: ", time.time() - timeStart) timeStart = time.time() predictions, probabilities = prediction.predictImage("./picture.jpg", result_count=5) for eachPrediction, eachProbability in zip(predictions, probabilities): print(str(eachPrediction) + " : " + str(eachProbability)) print("Predict Time: ", time.time() - timeStart)Copy the code

Execution Result:

Load Time: 5.549695014953613 LAPTOP: 71.43893241882324 Notebook: 16.265612840652466 modem: 4.899394512176514 HARD_disc: 4.007557779550552 mouse: 1.2981942854821682 Predict Time: 0.8137111663818359Copy the code

As you can see, it takes 5.5 seconds to load the imageAI module and the model file, and less than 1 second for the prediction part. In the function calculation, the machine performance itself is not as good as my local performance, and in order to avoid long response times each time the model is loaded, you can see in the deployed code that the model loading process is actually placed outside the entry method. One advantage of this is that the project does not necessarily have a cold start each time it executes, which means that some objects can be reused under certain reuse conditions, i.e. you do not have to reload the model, import dependencies, and so on each time.

So in a real project, in order to avoid frequent requests, instances repeatedly load, create some resources, we can put some resources at the time of initialization. In this way, the overall performance of the project can be greatly improved, and at the same time, with the reserved capacity provided by the manufacturer, the negative impact brought by the cold start of the function can be basically eliminated.

conclusion

In recent years, with the rapid development of artificial intelligence and cloud computing, how to run traditional ARTIFICIAL intelligence projects in Serverless architecture has gradually become something that many people need to know. This paper mainly introduces an image classification and prediction interface based on an existing dependency library (ImageAI). Using this example, a few things can be made clear:

  • The Serverless architecture can run ai related projects;
  • Serverless is well compatible with machine learning/deep learning tools like Tensorflow;
  • Although the function computation itself has space limitation, but actually increases the hard disk mount capacity, the function computation capability itself will be greatly expanded.

Of course, this article is a bit of a kick in the ass, and I hope you can use your imagination after this article to further integrate more AI projects with the Serverless architecture.