前端开发想了解机器学习?用一台Mac就可以

Posted 淘系技术

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了前端开发想了解机器学习?用一台Mac就可以相关的知识,希望对你有一定的参考价值。


可能有些同学学习机器学习的时候比较迷茫,不知道该怎么上手,看了很多经典书籍介绍的各种算法,但还是不知道怎么用它来解决问题,就算知道了,又发现需要准备环境、准备训练和部署的机器,啊,好麻烦。

今天,我来给大家介绍一种容易上手的方法,给你现成的样本和代码,按照步骤操作,就可以在自己的 Mac 上体验运用机器学习的全流程啦~~~



下面的 Demo, 最终的效果是给定一张图片,可以预测图片的类别。比如我们训练模型用的样本是猫啊狗啊,那模型能学到的认识的就是猫啊狗啊, 如果用的训练样本是按钮啊搜索框啊,那模型能学到的认识的就是这个按钮啊搜索框啊。

如果想了解用机器学习是怎么解决实际问题的,可以看这篇: 从问题定义、算法选型、样本准备、模型训练、模型评估、模型服务部署、到模型应用都有介绍。


环境准备



 安装 Anaconda


下载地址: https://www.anaconda.com/products/individual

前端开发想了解机器学习?用一台Mac就可以

安装成功后,在终端命令行执行以下命令,使环境变量立即生效:

  
    
    
  
$ source ~/.bashrc
 
   
   
 

可以执行以下命令,查看环境变量

  
    
    
  
$ cat ~/.bashrc
 
   
   
 

可以看到 anaconda 的环境变量已经自动添加到 .bashrc 文件了。

前端开发想了解机器学习?用一台Mac就可以

执行以下命令:

  
    
    
  
$ conda list
 
   
   
 

可以看到 Anaconda 中有很多已经安装好的包,如果有使用到这些包的就不需要再安装了,python 环境也装好了。

前端开发想了解机器学习?用一台Mac就可以

注意: 如果安装失败,重新安装,在提示安装在哪里时,选择「更改安装位置」,安装位置选择其他地方不是用默认的,安装在哪里自己选择,可以放在「应用程序」下。

前端开发想了解机器学习?用一台Mac就可以

 安装相关依赖


anaconda 中没有  keras、tensorflow 和  opencv-python, 需要单独安装。

  
    
    
  
$ pip install keras $ pip install tensorflow $ pip install opencv-python
 
   
   
 


样本准备



这里只准备了 4 个分类:button、keyboard、searchbar、switch, 每个分类 200 个左右的样本。

前端开发想了解机器学习?用一台Mac就可以
前端开发想了解机器学习?用一台Mac就可以
前端开发想了解机器学习?用一台Mac就可以
前端开发想了解机器学习?用一台Mac就可以


模型训练



 开发训练逻辑


新建一个项目 train-project, 文件结构如下:

  
    
    
  
. ├── CNN_net.py ├── dataset ├── nn_train.py └── utils_paths.py
 
   
   
 

入口文件代码如下,这里的逻辑是将准备好的样本输入给图像分类算法 SimpleVGGNet, 并设置一些训练参数,例如学习率、Epoch、Batch Size, 然后执行这段训练逻辑,最终得到一个模型文件。

  
    
    
  
# nn_train.py from CNN_net import SimpleVGGNet from sklearn.preprocessing import LabelBinarizer from sklearn.model_selection import train_test_split from sklearn.metrics import classification_report from keras.optimizers import SGD from keras.preprocessing.image import ImageDataGenerator import utils_paths import matplotlib.pyplot as plt from cv2 import cv2 import numpy as np import argparse import random import pickle import os # 读取数据和标签 print("------开始读取数据------") data = [] labels = [] # 拿到图像数据路径,方便后续读取 imagePaths = sorted(list(utils_paths.list_images('./dataset'))) random.seed(42) random.shuffle(imagePaths) image_size = 256 # 遍历读取数据 for imagePath in imagePaths: # 读取图像数据 image = cv2.imread(imagePath) image = cv2.resize(image, (image_size, image_size)) data.append(image) # 读取标签 label = imagePath.split(os.path.sep)[-2] labels.append(label) data = np.array(data, dtype="float") / 255.0 labels = np.array(labels) # 数据集切分 (trainX, testX, trainY, testY) = train_test_split(data,labels, test_size=0.25, random_state=42) # 转换标签为one-hot encoding格式 lb = LabelBinarizer() trainY = lb.fit_transform(trainY) testY = lb.transform(testY) # 数据增强处理 aug = ImageDataGenerator( rotation_range=30, width_shift_range=0.1, height_shift_range=0.1, shear_range=0.2, zoom_range=0.2, horizontal_flip=True, fill_mode="nearest") # 建立卷积神经网络 model = SimpleVGGNet.build(width=256, height=256, depth=3,classes=len(lb.classes_)) # 设置初始化超参数 # 学习率 INIT_LR = 0.01 # Epoch # 这里设置 5 是为了能尽快训练完毕,可以设置高一点,比如 30 EPOCHS = 5 # Batch Size BS = 32 # 损失函数,编译模型 print("------开始训练网络------") opt = SGD(lr=INIT_LR, decay=INIT_LR / EPOCHS) model.compile(loss="categorical_crossentropy", optimizer=opt,metrics=["accuracy"]) # 训练网络模型 H = model.fit_generator( aug.flow(trainX, trainY, batch_size=BS), validation_data=(testX, testY), steps_per_epoch=len(trainX) // BS, epochs=EPOCHS ) # 测试 print("------测试网络------") predictions = model.predict(testX, batch_size=32) print(classification_report(testY.argmax(axis=1), predictions.argmax(axis=1), target_names=lb.classes_)) # 绘制结果曲线 N = np.arange(0, EPOCHS) plt.style.use("ggplot") plt.figure() plt.plot(N, H.history["loss"], label="train_loss") plt.plot(N, H.history["val_loss"], label="val_loss") plt.plot(N, H.history["accuracy"], label="train_acc") plt.plot(N, H.history["val_accuracy"], label="val_acc") plt.title("Training Loss and Accuracy") plt.xlabel("Epoch #") plt.ylabel("Loss/Accuracy") plt.legend() plt.savefig('./output/cnn_plot.png') # 保存模型 print("------保存模型------") model.save('./cnn.model.h5') f = open('./cnn_lb.pickle', "wb") f.write(pickle.dumps(lb)) f.close()
 
   
   
 

对于实际应用场景下,数据集很大,epoch 也会设置比较大,并在高性能的机器上训练。现在要在本机 Mac 上完成训练任务,我们只给了很少的样本来训练模型,epoch 也很小(为 5),当然这样模型的识别准确率也会很差,但我们此篇文章的目的是为了在本机完成一个机器学习的任务。

 开始训练


执行以下命令开始训练:

  
    
    
  
$ python nn_train.py
 
   
   
 

训练过程日志如下:

前端开发想了解机器学习?用一台Mac就可以

训练结束后,在当前目录下会生成两个文件:模型文件 cnn.model.h5 和 损失函数曲线 output/cnn_plot.png

前端开发想了解机器学习?用一台Mac就可以


模型评估



现在,我们拿到了模型文件 cnn.model.h5, 可以写一个预测脚本,本地执行脚本预测一张图片的分类。

  
    
    
  
$ python predict.py
 
   
   
 

  
    
    
  
# predict.py import allspark import io import numpy as np import json from PIL import Image import requests import threading import cv2 import os import tensorflow as tf from tensorflow.keras.models import load_model import time model = load_model('./train/cnn.model.h5') # pred的输入应该是一个images的数组,而且图片都已经转为numpy数组的形式 # pred = model.predict(['./validation/button/button-demoplus-20200216-16615.png']) #这个顺序一定要与label.json顺序相同,模型输出是一个数组,取最大值索引为预测值 Label = [ "button", "keyboard", "searchbar", "switch" ] testPath = "./test/button.png" images = [] image = cv2.imread(testPath) image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB) image = cv2.resize(image,(256,256)) images.append(image) images = np.asarray(images) pred = model.predict(images) print(pred) max_ = np.argmax(pred) print('预测结果为:',Label[max_])
 
   
   
 

如果想要知道这个模型的准确率,也可以给模型输入一批带有已知分类的数据,通过模型预测后,将模型预测的分类与真实的分类比较,计算出准确率和召回率。


模型服务部署



 开发模型服务


但在实际应用中,我们预测一张图片的类别, 是通过给定一张图片,请求一个 API 来拿到返回结果的。我们需要编写一个模型服务,然后部署到远端,拿到一个部署之后的模型服务 API。

现在,我们可以编写一个模型服务,然后在本地部署。

 
   
   
 
  
    
    
  
# 模型服务 app.py import allspark import io import numpy as np import json from PIL import Image import requests import threading import cv2 import tensorflow as tf from tensorflow.keras.models import load_model with open('label.json') as f: mp = json.load(f) labels = {value:key for key,value in mp.items()} def create_opencv_image_from_stringio(img_stream, cv2_img_flag=-1): img_stream.seek(0) img_array = np.asarray(bytearray(img_stream.read()), dtype=np.uint8) image_temp = cv2.imdecode(img_array, cv2_img_flag) if image_temp.shape[2] == 4: image_channel3 = cv2.cvtColor(image_temp, cv2.COLOR_BGRA2BGR) image_mask = image_temp[:,:,3] #.reshape(image_temp.shape[0],image_temp.shape[1], 1) image_mask = np.stack((image_mask, image_mask, image_mask), axis = 2) index_mask = np.where(image_mask == 0) image_channel3[index_mask[0], index_mask[1], index_mask[2]] = 255 return image_channel3 else: return image_temp def get_string_io(origin_path): r = requests.get(origin_path, timeout=2) stringIo_content = io.BytesIO(r.content) return stringIo_content def handleReturn(pred, percent, msg_length): result = { "content":[] } argm = np.argsort(-pred, axis = 1) for i in range(msg_length): label = labels[argm[i, 0]] index = argm[i, 0] if(pred[i, index] > percent): confident = True else: confident = False result['content'].append({'isConfident': confident, 'label': label}) return result def process(msg, model): msg_dict = json.loads(msg) percent = msg_dict['threshold'] msg_dict = msg_dict['images'] msg_length = len(msg_dict) desire_size = 256 images = [] for i in range(msg_length): image_temp = create_opencv_image_from_stringio(get_string_io(msg_dict[i])) image_temp = cv2.cvtColor(image_temp, cv2.COLOR_BGR2RGB) image = cv2.resize(image_temp, (256, 256)) images.append(image) images = np.asarray(images) pred = model.predict(images) return bytes(json.dumps(handleReturn(pred, percent, msg_length)) ,'utf-8') def worker(srv, thread_id, model): while True: msg = srv.read() try: rsp = process(msg, model) srv.write(rsp) except Exception as e: srv.error(500,bytes('invalid data format', 'utf-8')) if __name__ == '__main__': desire_size = 256 model = load_model('./cnn.model.h5') context = allspark.Context(4) queued = context.queued_service() workers = [] for i in range(10): t = threading.Thread(target=worker, args=(queued, i, model)) t.setDaemon(True) t.start() workers.append(t) for t in workers: t.join()


 部署模型服务


模型服务编写完成后,在本地部署,需要安装环境。首先创建一个模型服务项目: deploy-project, 将 cnn.model.h5 拷贝到此项目中, 并在此项目下安装环境。

 
   
   
 
  
    
    
  
. ├── app.py ├── cnn.model.h5 └── label.json


✎  安装环境


可以看下 阿里云的模型服务部署文档 :3、Python语言-3.2 构建开发环境-3.2.3 使用预构建的开发镜像(推荐)

安装 Docker

可以直接查看 Mac Docker 安装文档

  
    
    
  
# 用 Homebrew 安装 需要先现状 Homebrew: https://brew.sh $ brew cask install docker
 
   
   
 

安装完之后,桌面上会出现 Docker 的图标。

创建 anaconda 的虚拟环境

  
    
    
  
# 使用conda创建python环境,目录需指定固定名字:ENV $ conda create -p ENV python=3.7 # 安装EAS python sdk $ ENV/bin/pip install http://eas-data.oss-cn-shanghai.aliyuncs.com/sdk/allspark-0.9-py2.py3-none-any.whl # 安装其它依赖包 $ ENV/bin/pip install tensorflow keras opencv-python # 激活虚拟环境 $ conda activate ./ENV # 退出虚拟环境(不使用时) $ conda deactivate
 
   
   
 

运行 Docker 环境

/Users/chang/Desktop/ml-test/deploy-project 换成自己的项目路径

  
    
    
  
sudo docker run -ti -v /Users/chang/Desktop/ml-test/deploy-project:/home -p 8080:8080 registry.cn-shanghai.aliyuncs.com/eas/eas-python-base-image:py3.6-allspark-0.8
 
   
   
 

✎  本地部署


现在可以本地部署了,执行以下命令:

  
    
    
  
cd /home ./ENV/bin/python app.py
 
   
   
 

下面的日志可以看到部署成功。

前端开发想了解机器学习?用一台Mac就可以

部署成功后,可以通过 localhost:8080/predict 访问模型服务了。

我们用 curl 命令来发一个 post 请求, 预测图片分类:

  
    
    
  
curl -X POST 'localhost:8080/predict' -H 'Content-Type: application/json' -d '{ "images": ["https://img.alicdn.com/tfs/TB1W8K2MeH2gK0jSZJnXXaT1FXa-638-430.png"], "threshold": 0.5 }'

得到预测结果:

  
    
    
  
{"content": [{"isConfident": true, "label": "keyboard"}]}
 
   
   
 


完整代码



可以直接 clone 代码仓库: https://github.com/imgcook/ml-mac-classify

在安装好环境后,直接按以下命令运行。

 
   
   
 
  
    
    
  
# 1、训练模型 $ cd train-project $ python nn_train.py # 生成模型文件:cnn.model.h5 # 2、将模型文件拷贝到 deploy-project 中,部署模型服务 # 先安装模型服务运行环境 $ conda activate ./ENV $ sudo docker run -ti -v /Users/chang/Desktop/ml-test/deploy-project:/home -p 8080:8080 registry.cn-shanghai.aliyuncs.com/eas/eas-python-base-image:py3.6-allspark-0.8 $ cd /home $ ./ENV/bin/python app.py # 得到模型服务 API:localhost:8080/predict # 3、访问模型服务 curl -X POST 'localhost:8080/predict' -H 'Content-Type: application/json' -d '{ "images": ["https://img.alicdn.com/tfs/TB1W8K2MeH2gK0jSZJnXXaT1FXa-638-430.png"], "threshold": 0.5 }'



最后



好啦,总结一下这里使用深度学习的流程。我们选用了 SimpleVGGNet  作为图像分类算法(相当于一个函数),将准备好的数据传给这个函数,运行这个函数(学习数据集的特征和标签)得到一个输出,就是模型文件 model.h5。

前端开发想了解机器学习?用一台Mac就可以

这个模型文件可以接收一张图片作为输入,并预测这张图片是什么,输出预测结果。但如果想要让模型可以在线上跑,需要写一个模型服务(API)并部署到线上以得到一个 HTTP API,我们可以在生产环境直接调用。


One More Thing

我们是 阿里巴巴-淘系技术部-频道与D2C智能团队 ,致力于前端智能化领域的探索和实践,赋能淘宝、天猫、聚划算等日常与大促(如双 11 )业务,是淘系前端智能化实践的领路人,也是阿里经济体前端委员会智能化方向的核心团队。

目前团队有较多高校和海外背景的技术小二,专业领域涉及 前端、算法、全栈 等。我们在 D2C(Design to Code) 领域开放了  Imgcook(https://www.imgcook.com) 平台,在逐步释放阿里生态的前端生产力;我们也与 Google 的 tensorflow 团队保持长线合作,基于 tfjs-node 之上,开源了我们的前端算法工程框架 Pipc ook(https://github.com/alibaba/pipcook) ,在引领前端行业向智能化时代迈进。

简历投递至

以上是关于前端开发想了解机器学习?用一台Mac就可以的主要内容,如果未能解决你的问题,请参考以下文章

web前端开发JQuery常用实例代码片段(50个)

一百行代码实现简易版 ChatGPT 聊天机器人

一百行代码实现简易版 ChatGPT 聊天机器人

前端到docker入门

机器学习中的微分和矩阵

简单了解学习PHP(针对前端开发)