乐趣区

关于人工智能:使用Flask部署图像分类模型

作者 |LAKSHAY ARORA
编译 |VK
起源 |Analytics Vidhya

概述

  • 理解 PyTorch 和 Flask 的详情
  • 学习在 PyTorch 中建设图像分类模型
  • 理解如何应用 Flask 部署模型。

介绍

当波及到社交媒体的衰弱运行时,图像分类是一个关键点。依据特定标签对内容进行分类能够代替各种法律法规。它变得很重要,以便对特定的受众群体暗藏内容。

当我在 Instagram 上浏览时,我常常会遇到一些图片上有“敏感内容”的帖子。我必定你也有。

任何无关人道主义危机、恐怖主义或暴力的图片通常被归类为“敏感内容”。Instagram 如何对图片进行分类始终让我很感兴趣。这种一直的好奇心促使我去了解图像分类的过程。

大部分图像是由 Instagram 部署的图像分类模型检测进去的。此外,还有一个基于社区的反馈循环。这是图像分类最重要的用例之一。

在本文中,咱们将部署一个图像分类模型来检测图像的类别。

目录

  1. 什么是模型部署?
  2. PyTorch 简介
  3. 什么是 Flask?
  4. 在机器上装置 Flask 和 PyTorch
  5. 了解问题陈说
  6. 建设预训练的图像分类模型
  7. 建设一个图像 Scraper
  8. 创立网页
  9. 设置 Flask 我的项目
  10. 部署模型的工作

什么是模型部署

在典型的机器学习和深度学习我的项目中,咱们通常从定义问题陈说开始,而后是数据收集和筹备,而后是模型构建,对吗?

一旦咱们胜利地构建和训练了模型,咱们心愿它能为最终用户所用。

因而,咱们必须“部署”模型,以便最终用户能够应用它。模型部署是任何机器学习或深度学习我的项目的前期阶段之一。

在本文中,咱们将在 PyTorch 中构建一个分类模型,而后学习如何应用 Flask 部署雷同的模型。在咱们进入细节之前,让咱们先简略介绍一下 PyTorch。

PyTorch 简介

PyTorch 是一个基于 python 的库,它提供了作为深度学习开发平台的灵活性。PyTorch 的工作流程与 python 的科学计算库 NumPy 十分靠近。

PyTorch 被宽泛用于构建深度学习模型。以下是 PyTorch 的一些重要劣势

  • 易于应用的 API–PyTorch API 与 python 一样简略。
  • Python 反对—PyTorch 与 Python 完满集成。
  • 动静计算图——PyTorch 为咱们提供了一个框架来构建计算图,甚至在运行时扭转它们。这对于咱们不晓得创立一个神经网络须要多少内存的状况很有价值。

在接下来的章节中,咱们将应用一个预训练的模型来应用 PyTorch 来检测图像的类别。接下来,咱们将应用 Flask 进行模型部署。在下一节中,咱们将简要探讨 Flask。

什么是 Flask?

Flask 是一个用 Python 编写的 web 应用程序框架。它有多个模块,使 web 开发人员更容易编写应用程序,而不用放心协定治理、线程治理等细节。

Flask 为开发 web 应用程序提供了多种抉择,并为咱们提供了构建 web 应用程序所需的工具和库。

在机器上装置 Flask 和 PyTorch

装置 Flask 简单明了。这里,我假如你曾经装置了 python3 和 pip。要装置 Flask,须要运行以下命令:

sudo apt-get install python3-flask

接下来,咱们须要装置 PyTorch。运行本文中提供的代码不须要有 GPU。

!pip install torch torchvision

就这样!当初让咱们开始一个问题陈说并建设一个模型。

了解问题陈说

让咱们讨论一下问题陈说,咱们想要创立一个蕴含如下文本框的网页(如下所示)。用户在这里输出网址。

这里的工作是从 URL 中抓取所有图像。对于每个图像,咱们将应用图像分类模型预测图像的类别或类别,并在网页上按类别出现图像。

上面是端到端模型的工作流 -

设置我的项目工作流

  • 模型构建 :咱们将应用预训练的模型Densenet 121 来预测图像类。它能够在 PyTorch 的 torchvision 库中找到。这里,咱们的重点不是从头开始构建一个高度准确的分类模型,而是看看如何部署该模型并在 web 界面中应用它。
  • 创立一个图像 Scraper:咱们将应用申请和 BeautifulSoup 库创立一个 web scraper。它将从一个 URL 下载所有的图像并将其存储,这样咱们就能够对其进行预测。
  • 设计网页模板:咱们还将设计一个用户界面,用户能够提交一个网址,也能够失去后果,一旦计算。
  • 对图像进行分类并发送后果:一旦咱们从用户那里失去查问,咱们将应用该模型预测图像的类别并将后果发送给用户。

上面是咱们刚刚看到的步骤的一个示意:

让咱们讨论一下我的项目所需的所有组成部分:

建设预训练的图像分类模型

咱们将应用预训练的模型 Densenet 121 对图像进行分类。

你能够在这里下载残缺的代码和数据集。

链接:https://github.com/lakshay-ar…

让咱们从导入一些必须的库开始,并从 torchvision 库获取 densenet121 模型。确保将参数“pretrained”增加为 True。

# 导入所需的库
import json
import io
import glob
from PIL import Image
from torchvision import models
import torchvision.transforms as transforms

# 将参数“pretraining”传递为“True”,应用预训练的权重:
model = models.densenet121(pretrained=True)
# 切换到模型到“eval”模式:
model.eval()

当初,咱们将定义一个函数来转换图像。它将创立一个转换管道并依据须要转换图像。此办法以字节为单位获取图像数据,并对其利用一系列“转换”函数并返回张量。这段代码取自 pytorch 文档。

# 定义预处理的函数
def transform_image(image_bytes):
    my_transforms = transforms.Compose([transforms.Resize(255),
                                        transforms.CenterCrop(224),
                                        transforms.ToTensor(),
                                        transforms.Normalize([0.485, 0.456, 0.406],
                                            [0.229, 0.224, 0.225])])
    image = Image.open(io.BytesIO(image_bytes))
    return my_transforms(image).unsqueeze(0)

当初,预训练的模型返回预测类 id 的索引。PyTorch 曾经为它提供了映射,以便咱们能够看到预测类的名称。你能够在这里下载地图。它有 1000 个不同的类别。

# 加载由 pytorch 提供的映射
imagenet_class_mapping = json.load(open('imagenet_class_index.json'))

上面是一个示例:

接下来,咱们将定义一个函数来获取图像的类别。为此,咱们将图像的门路作为惟一的参数传递。

首先,它将关上并读取二进制格局的图像,而后对其进行转换。而后将变换后的图像传递给模型,失去预测类。它将应用映射并返回类名。

# 定义函数来取得图片的预测
# 它承受参数: 图片门路并提供预测作为输入
def get_category(image_path):
  #以二进制模式读取图像
    with open(image_path, 'rb') as file:
        image_bytes = file.read()
    # 变换图像
    transformed_image = transform_image(image_bytes=image_bytes)
    # 应用模型来预测类
    outputs = model.forward(transformed_image)
    _, category = outputs.max(1)
    # 返回
    predicted_idx = str(category.item())
    return imagenet_class_mapping[predicted_idx]

让咱们在一些图像上尝试此函数:

get_category(image_path='static/sample_1.jpeg')
## ['n02089973', 'English_foxhound']

get_category(image_path='static/sample_2.jpeg')
## ['n11939491', 'daisy']

当初,咱们的模型能够预测图像的类。让咱们从构建图像 Scraper 开始。

建设一个图像 Scraper

在本节中,咱们将构建一个 web scraper,它将从提供的 URL 下载图像。咱们将应用 BeautifulSoup 库下载图像。你能够自在应用任何其余库或 API 来提供图像。

咱们将从导入一些必须的库开始。对于咱们将抓取的每个 url,将创立一个新目录来存储图像。咱们将创立一个函数 get_path,它将返回为该 URL 创立的文件夹的门路。

# 导入所需的库
import requests
from bs4 import BeautifulSoup
import os
import time

def get_path(url):
    return "static/URL_" + str(url.replace("/","_"))
  
headers = {'User-Agent': "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.90 Safari/537.36"
    } 

当初,咱们将定义一个函数 get_images。它将首先应用 get_path 函数创立目录,而后发送对源代码的申请。从源代码中,咱们将应用“img”标签提取源代码。

在此之后,咱们将只抉择 jpeg 格局的图像。也能够增加 png 格局的图像。我曾经过滤掉了,因为大多数 png 格局的图片都是 logo。

最初,启动计数器并将带有计数器名称的图像保留到指定的目录中。

# 定义爬取图像并将其存储在目录中的函数
def get_images(url):
   # get the directory path
    path = get_path(url)
    try:
        os.mkdir(path)
    except:
        pass
    # 从 URL 申请源代码
    response = requests.request("GET", url, headers=headers)
    # 通过 Beautiful Soup 解析数据
    data = BeautifulSoup(response.text, 'html.parser')
    # 在源代码中找到图像标记
    images = data.find_all('img', src=True)
    # 从所有的图像标签中提取 src
    image_src = [x['src'] for x in images]
    # 只抉择 jpeg
    image_src = [x for x in image_src if x.endswith('.jpeg') ]
    image_count = 1
    # 在指定目录存储图像
    for image in image_src:
        print(image)
        image_file_name = path+'/'+str(image_count)+'.jpeg' 
        print(image_file_name)
        # 以写入二进制模式关上文件并增加图像内容来存储它
        with open(image_file_name, 'wb') as f:
            res = requests.get(image)
            f.write(res.content)
        image_count = image_count+1

让咱们试试咱们刚刚发明的 scraper!

get_images('https://medium.com/@allanishac/9-wild-animals-that-would-make-a-much-better-president-than-donald-trump-b41f960bb171')

当初,创立了一个新目录,并查看它的外观。咱们在一个中央下载了所有的图片。

留神:倡议仅依据学习目标应用此图像 Scraper。始终遵循指标网站的 robots.txt 文件,也称为机器人排除协定。这会通知网络机器人哪些页面不能爬。

创立网页

咱们将创立两个网页一个是“home.html另一个是“image_class.html”.

  • home.html“是默认的,它将有一个文本框,用户能够在其中键入 URL。
  • image_class.html“将帮忙咱们按类别渲染图像。

1.home.html

咱们须要在 home.html 文件以收集搜寻容器中的数据。在 form 标签中,咱们将应用 post 办法,并且数据通过名为“search”的输出栏传递。

通过这样做,咱们的后端代码将可能晓得咱们收到了一些名为“search”的数据。在后端,咱们须要解决并发送数据。

2.image_class.html

在计算结果时,另一个页面将出现如下后果。本页“image_class.html“将在每次查问时更新。你能够看到咱们在网页上显示了以下信息:

  1. 图像类别
  2. 图像
  3. 所有可用图像类别的频率计数

上面是执行此操作的代码:

def get_picture_html(path, tag):
    image_html = """<p> {tag_name} </p> <picture> <img src="../{path_name}"height="300"width="400"> </picture>"""
    return image_html.format(tag_name=tag, path_name=path)

# 定义在 html 文件中增加列表元素的函数
def get_count_html(category, count):
    count_html = """<li> {category_name} : {count_} </li>"""
    return count_html.format(category_name = category, count_ = count)

# 计数
def get_value_count(image_class_dict):
    count_dic = {}
    for category in image_class_dict.values():
        if category in count_dic.keys():
            count_dic[category] = count_dic[category]+1
        else:
            count_dic[category] = 1
    return count_dic

# 函数从 image_class 字典生成 html 文件
# 键将是图像的门路,而值将是与之关联的类。def generate_html(image_class_dict):
    picture_html = ""count_html =""
    
    # 循环这些键并将图像增加到 html 文件中
    for image in image_class_dict.keys():
        picture_html += get_picture_html(path=image, tag= image_class_dict[image])
        
    value_counts = get_value_count(image_class_dict)
    
    # 循环 value_counts 并向 html 文件中增加类的计数
    for value in value_counts.keys():
        count_html += get_count_html(value, value_counts[value])

下一步是建设 Flask 我的项目,将这些独自的局部组合起来解决这个挑战。

设置 Flask 我的项目

咱们在我的项目中实现了以下工作:

  1. 图像分类模型工作良好,可能对图像进行分类。
  2. 咱们曾经建设了图像 Scraper,将下载图像并存储它们。
  3. 咱们曾经创立了网页来获取并返回后果。

当初咱们须要将所有这些文件连贯在一起,这样咱们就能够有一个工作我的项目了。

让咱们看看目录构造。

留神 :请确保将图像保留在static 文件夹和 html 文件放在 templates 文件夹中。Flask 只会查找这些名字。如果你扭转这些,你会失去一个谬误。

运行 Flask 应用程序

Flask 应用程序首先将 home.html 当有人发送图像分类申请时,Flask 将检测一个 post 办法并调用 get_image_class 函数。

此函数将按以下步骤工作:

  1. 首先,它将发送一个申请来下载并存储这些图像。
  2. 接下来,它将把目录门路发送到 get_prediction.py 将计算并以字典模式返回后果的文件。
  3. 最初,它将把这个字典发送给generate_html.py,用户将返回生成该文件的输入。

# 导入库
from flask import Flask, render_template, request, redirect, url_for
from get_images import get_images, get_path, get_directory
from get_prediction import get_prediction
from generate_html import generate_html
from torchvision import models
import json

app = Flask(__name__)

# 映射
imagenet_class_mapping = json.load(open('imagenet_class_index.json'))

# 应用预训练模型
model = models.densenet121(pretrained=True)
model.eval()

# 定义从 url 获取图像并预测类的函数
def get_image_class(path):
    # 从 URL 获取图像并将其存储在给定的门路中
    get_images(path)
    # 依据所提供的目录预测图像的图像类别
    path = get_path(path)
    images_with_tags = get_prediction(model, imagenet_class_mapping, path)
    # 生成 html 文件以在咱们预测类之后出现
    generate_html(images_with_tags)

一旦以上步骤实现,咱们就能够为用户提供后果。咱们将调用 success 函数,该函数将渲染 image_class.html 文件。

# 根页面为 "home.html"    
@app.route('/')
def home():
    return render_template('home.html')

@app.route('/', methods=['POST', 'GET'])
def get_data():
    if request.method == 'POST':
        user = request.form['search']
        # 如果搜寻按钮被点击,调用函数 get_image_class
        get_image_class(user)
        #返回 image_class.html
        return redirect(url_for('success', name=get_directory(user)))


@app.route('/success/<name>')
def success(name):
    return render_template('image_class.html')


if __name__ == '__main__' :
    app.run(debug=True)

获取源 URL 的所有图像的预测

到目前为止,咱们曾经别离对每幅图像进行了预测。当初,咱们将用新参数批改 get_category 函数来解决这个问题。咱们将传递蕴含多个图像文件的目录门路。

当初,咱们将定义另一个函数 get_prediction,它将应用 get_category 函数并返回字典,其中键将是图像门路,值将是图像类。

稍后,咱们将把这个字典发送给 generate_html.py 将为咱们创立 HTML 文件的文件。

# 获取目录中呈现的所有图像的类
def get_category(model, imagenet_class_mapping, image_path):
    with open(image_path, 'rb') as file:
        image_bytes = file.read()
    transformed_image = transform_image(image_bytes=image_bytes)
    outputs = model.forward(transformed_image)
    _, category = outputs.max(1)
    
    predicted_idx = str(category.item())
    return imagenet_class_mapping[predicted_idx]

# 它将创立一个图像门路和预测类的字典
# 咱们将应用该字典生成 html 文件。def get_prediction(model, imagenet_class_mapping, path_to_directory):
    files = glob.glob(path_to_directory+'/*')
    image_with_tags = {}
    for image_file in files:
        image_with_tags[image_file] = get_category(model, imagenet_class_mapping, image_path=image_file)[1]
    return image_with_tags

当初,所有的代码文件都筹备好了,咱们只须要将它们与主文件连接起来。

首先,创立一个 Flask 类的对象,该对象将以以后模块的名称作为参数。route 函数将通知 Flask 应用程序下一步在网页上出现哪个 URL。

部署模型的工作

你能够在这里下载残缺的代码和数据集。

链接:https://github.com/lakshay-ar…

当初,咱们运行 get_class.py,Flask 服务器就能够在 localhost:5000 启动

关上 web 浏览器并转到 localhost:5000,你将看到默认主页在那里出现。当初,在文本框中输出任何 URL 并按 search 按钮。这可能须要 20-30 秒,这取决于网址中的图片数量和网速。

让咱们看看部署模型的工作状况。

视频:https://cdn.analyticsvidhya.c…

结尾

在本文中,我简要地解释了模型部署、Pytorch 和 Flask 的概念。

而后咱们深刻理解了应用 PyTorch 创立图像分类模型并将其与 Flask 一起部署的过程中波及的各个步骤。我心愿这有助于你构建和部署图像分类模型。

另外,模型被部署在本地主机上。咱们也能够把它部署在云服务上,比方 Google Cloud,Amazon,github.io 等等,咱们也将在下一篇文章中探讨这一点。

原文链接:https://www.analyticsvidhya.c…

欢送关注磐创 AI 博客站:
http://panchuang.net/

sklearn 机器学习中文官网文档:
http://sklearn123.com/

欢送关注磐创博客资源汇总站:
http://docs.panchuang.net/

退出移动版