[PYTHON] Erstellen Sie eine App für maschinelles Lernen mit ABEJA Platform + LINE Bot

Dieser Artikel ist der zweite Tagesartikel von ABEJA Adventskalender 2019.

Im letztjährigen ABEJA Platform Advent Calendar heißt es: "[Zusammenfassung der ABEJA Platform-Zertifizierung](https://qiita.com/ishikawa@github/items/ Ich habe die Authentifizierung von API-Aufrufen in ABEJA Platform unter dem Titel "150a0705d9581c1000c6)" eingeführt, aber ich habe sie auch in diesem Jahr in ABEJA Platform-Material geschrieben.

Leider unterstützt die ABEJA-Plattform Elixir nicht, sodass der gesamte Code in Python geschrieben ist.

Überblick

Gepostet im Juli 2019 von @yushin_n "[ABEJA-Plattform + Cloud-Funktionen + LINE-Bot zum Erstellen einer App für maschinelles Lernen](https: // qiita. com / yushin_n / items / 0d115efa705579a53cfe) "

Das Thema war, durch Kombinieren eine serverlose App für maschinelles Lernen zu erstellen.

Dieses Mal werde ich das Verfahren zur Verbesserung dieser App für maschinelles Lernen vorstellen und ** LINE Bot nur auf der ABEJA-Plattform ohne Verwendung von Google Cloud-Funktionen entwickeln **.

Zu diesem Zweck werden in diesem Artikel die folgenden drei Funktionen der ABEJA-Plattform verwendet:

Neues Containerbild

Die ABEJA-Plattform ist grob unterteilt in 18.10 und 19.x series. Wir bieten zwei Arten von Bildern an (/model-handler-19.04/). In der 19.x-Serie werden nicht nur neuere Bibliotheken und Frameworks installiert, sondern auch die Implementierungsmethode der API für maschinelles Lernen wurde überarbeitet, damit eine flexiblere Verarbeitung implementiert werden kann.

Inferenzvorlage

Die ABEJA-Plattform bietet Lern- und Inferenzvorlagen für einige maschinelle Lernaufgaben. Mit dieser Vorlage können Sie nicht nur Modelle für maschinelles Lernen lernen und ableiten, ohne eine einzige Codezeile zu schreiben, sondern sie eignet sich auch für die Geschäftsdomäne (diesmal LINE-Bot für die Bildklassifizierung), die Sie durch Ändern des Codes implementieren möchten. Kann verbessert werden.

API-Endpunktauthentifizierungsmethode

Sie können die Authentifizierungsmethode für die bereitgestellte API auswählen. Sie können nicht nur zwischen integrierter Benutzerauthentifizierung und API-Schlüsselauthentifizierung wählen, sondern auch die Authentifizierung selbst deaktivieren und Ihre eigene Verarbeitung implementieren. Die LINE-Bot-Implementierung verwendet diese Funktion, um die Authentifizierung zur Signaturüberprüfung zu implementieren.

Systemkonfiguration

ABEJA_Platform_LINEbot_Arch.png

Implementierung des Inferenzcodes

In "Modell des maschinellen Lernens ohne Programmierung mit der ABEJA-Plattformvorlage lernen" wurde das Netzwerktraining bereits abgeschlossen und die daraus resultierenden Parameter Wird als "Modell" der ABEJA-Plattform gespeichert.

スクリーンショット 2019-12-01 18.18.38.png

Erstellen Sie die erste Version aus der Vorlage

Ich möchte den Inferenzcode nicht von Grund auf neu schreiben, daher werde ich den Code in der Inferenzvorlage der ABEJA-Plattform ändern. In der Inferenzvorlage

Da die Verarbeitung implementiert ist, sollten Sie hier die für den LINE-Bot spezifische Verarbeitung hinzufügen (Details werden später beschrieben).

Um den Code für die Inferenzvorlage zu generieren, müssen Sie eine "Bereitstellung" erstellen, bei der es sich um den Container handelt, der den Code (und die bereitgestellten Dienste) verwaltet. Erstellen Sie eine neue Bereitstellung über die Schaltfläche "Bereitstellung erstellen" im Bildschirm Bereitstellungsliste.

スクリーンショット 2019-12-01 18.28.45.png

Die neu erstellte Bereitstellung sollte als "0-Modellversion" aufgeführt sein. Über diesen Link gelangen Sie zum Codeverwaltungsbildschirm.

スクリーンショット 2019-12-01 18.33.00.png

Auf dem Bildschirm Codeverwaltung können Sie den Code, der zu dieser Bereitstellung gehört, versionieren. Erstellen Sie sofort eine neue Codeversion unter "Version erstellen" oben rechts.

スクリーンショット 2019-12-01 18.33.24.png

Dieses Mal möchte ich den Code der Vorlage ändern, also wählen Sie "Vorlage" auf der Registerkarte und wählen Sie "Bildklassifizierung (CPU)".

スクリーンショット 2019-12-01 18.33.43.png

Dies ist die neu erstellte Codeversion "0.0.1". Klicken Sie auf den Link, um zum einzelnen Bildschirm zu gelangen.

スクリーンショット 2019-12-01 18.34.10.png

Sie können die Quellcode-Zip-Datei über den Link "Download" auf dem einzelnen Bildschirm der Codeversion herunterladen.

スクリーンショット 2019-12-01 18.34.20.png

Verbessern Sie den Vorlagencode

Wenn Sie die heruntergeladene Zip-Datei entpacken, sollte eine Verzeichnisstruktur wie die folgende angezeigt werden.

$ ls -l 
total 96
-rw-r--r--@ 1 user  staff   1068 10 30 01:31 LICENSE
-rw-r--r--@ 1 user  staff   4452 10 30 01:31 README.md
-rw-r--r--@ 1 user  staff   1909 10 30 01:31 predict.py
-rw-r--r--@ 1 user  staff  12823 10 30 01:31 preprocessor.py
-rw-r--r--@ 1 user  staff     82 10 30 01:31 requirements-local.txt
-rw-r--r--@ 1 user  staff     25 10 30 01:31 requirements.txt
-rw-r--r--@ 1 user  staff   4406 10 30 01:31 train.py
drwxr-xr-x@ 6 user  staff    192 10 30 01:31 utils

Lesen Sie den Originalartikel und fügen Sie die erforderlichen Bibliotheken zu require.txt hinzu.

line-bot-sdk
googletrans
...

Und Predict.py ist eine Datei, die die Inferenzverarbeitung implementiert. Hier ist jedoch die für den LINE-Bot erforderliche Verarbeitung.

  1. Überprüfung der im Header gesendeten Signatur
  2. Holen Sie sich Bilddaten aus der LINE-Nachricht
  3. Antworten Sie auf das Ergebnis auf LINE

Es ist notwendig, zusätzlich zu implementieren.

Setzen Sie zuerst die Datei "Predict.py", wenn diese Implementierungen abgeschlossen sind. Wir ändern die "Handler" -Funktion, die der Einstiegspunkt für die Anfrage ist.

import os
import io
import linebot
import linebot.exceptions
import linebot.models
import googletrans

from keras.models import load_model
import numpy as np
from PIL import Image

from preprocessor import preprocessor
from utils import set_categories, IMG_ROWS, IMG_COLS


# Initialize model
model = load_model(os.path.join(os.environ.get(
    'ABEJA_TRAINING_RESULT_DIR', '.'), 'model.h5'))
_, index2label = set_categories(os.environ.get(
    'TRAINING_JOB_DATASET_IDS', '').split())

# (1) Get channel_secret and channel_access_token from your environment variable
channel_secret = os.environ['LINE_CHANNEL_SECRET']
channel_access_token = os.environ['LINE_CHANNEL_ACCESS_TOKEN']

line_bot_api = linebot.LineBotApi(channel_access_token)
parser = linebot.WebhookParser(channel_secret)


def decode_predictions(result):
    result_with_labels = [{"label": index2label[i],
                           "probability": score} for i, score in enumerate(result)]
    return sorted(result_with_labels, key=lambda x: x['probability'], reverse=True)


def handler(request, context):
    headers = request['headers']
    body = request.read().decode('utf-8')

    # (2) get X-Line-Signature header value
    signature = next(h['values'][0]
                     for h in headers if h['key'] == 'x-line-signature')

    try:
        # parse webhook body
        events = parser.parse(body, signature)
        for event in events:
            # initialize reply message
            text = ''

            # if message is TextMessage, then ask for image
            if event.message.type == 'text':
                text = 'Bitte senden Sie mir ein Bild!'

            # (3) if message is ImageMessage, then predict
            if event.message.type == 'image':
                message_id = event.message.id
                message_content = line_bot_api.get_message_content(message_id)

                img_io = io.BytesIO(message_content.content)
                img = Image.open(img_io)
                img = img.resize((IMG_ROWS, IMG_COLS))

                x = preprocessor(img)
                x = np.expand_dims(x, axis=0)

                result = model.predict(x)[0]
                sorted_result = decode_predictions(result.tolist())

                # translate english label to japanese
                label_en = sorted_result[0]['label']
                translator = googletrans.Translator()
                label_ja = translator.translate(label_en.lower(), dest='ja')

                prob = sorted_result[0]['probability']

                # set reply message
                text = f'{int(prob*100)}%Mit einer Wahrscheinlichkeit von{label_ja.text}ist!'

            line_bot_api.reply_message(
                event.reply_token,
                linebot.models.TextSendMessage(text=text))

    except linebot.exceptions.InvalidSignatureError:
        raise context.exceptions.ModelError('Invalid signature')

    return {
        'status_code': 200,
        'content_type': 'text/plain; charset=utf8',
        'content': 'OK'
    }

Codebeschreibung

Die Teile, die sich auf die Implementierung des LINE-Bots beziehen, sind in den Kommentaren nummeriert. Schauen wir uns das Schritt für Schritt an. Der andere als der hier beschriebene Code ist die Inferenzvorlage und der Originalartikel wie er ist.

1. Initialisierung des LINE Bot SDK

# (1) Get channel_secret and channel_access_token from your environment variable
channel_secret = os.environ['LINE_CHANNEL_SECRET']
channel_access_token = os.environ['LINE_CHANNEL_ACCESS_TOKEN']

line_bot_api = linebot.LineBotApi(channel_access_token)
parser = linebot.WebhookParser(channel_secret)

Hier verwenden wir das LINE Bot SDK, um den API-Client und den Nachrichten-Parser zu initialisieren. Es wird angenommen, dass die für die Initialisierung erforderlichen Parameter (privater Schlüssel und Zugriffstoken) als Umgebungsvariablen übergeben werden.

2. Überprüfung der Unterschrift

# (2) get X-Line-Signature header value
signature = next(h['values'][0]
                 for h in headers if h['key'] == 'x-line-signature')

try:
  # parse webhook body
  events = parser.parse(body, signature)

Überprüfen Sie die im HTTP-Anforderungsheader übergebene Signatur "X-Line-Signature" mit dem SDK. Der HTTP-Anforderungsheader wird in dem an die Handlerfunktion übergebenen "request" -Dikt gespeichert.

3. Lassen Sie das Bild in der Nachricht senden

# (3) if message is ImageMessage, then predict
if event.message.type == 'image':
  message_id = event.message.id
  message_content = line_bot_api.get_message_content(message_id)

  img_io = io.BytesIO(message_content.content)
  img = Image.open(img_io)
  img = img.resize((IMG_ROWS, IMG_COLS))

Ruft den Inhalt der Nachricht ab und konvertiert sie in ein PIL-Image-Objekt.

Bereitstellen eines Modells für maschinelles Lernen

Lassen Sie uns nun den resultierenden Quellcode in eine neue Codeversion komprimieren.

スクリーンショット 2019-12-01 19.10.45.png

Neue Codeversion

Zeigen Sie im vorherigen Codeverwaltungsbildschirm den Bildschirm zur Erstellung der neuen Codeversion an und laden Sie die Zip-Datei hoch. Setzen Sie zu diesem Zeitpunkt die Laufzeit (Container-Image) auf "** abeja-inc / all-cpu: 19.10 **" und legen Sie die erforderlichen Umgebungsvariablen fest.

スクリーンショット_2019-12-01_17_44_11.png

Bereitstellen der API

Stellen Sie die API wie unter "Bereitstellen eines maschinellen Lernmodells ohne Programmierung mit ABEJA Platform-Vorlagen" beschrieben bereit. Wiederholen Sie sie daher nicht. Hmm.

Wie ich zu Beginn erklärt habe, habe ich jedoch einen neuen Endpunkt erstellt, um die Anforderung vom LINE-Bot ohne "Authentifizierung" weiterzuleiten.

スクリーンショット 2019-12-01 17.49.02.png

Sie können die URL des neu erstellten Endpunkts über das Schülersymbol in der Serviceliste überprüfen.

スクリーンショット 2019-12-01 19.20.30.png

Es sollte das Format "https: // {ORGANIZATION_NAME} .api.abeja.io / deployments / {DEPLOYMENT_ID}" haben. Registrieren Sie dies als LINE Bot Webhook.

スクリーンショット_2019-12-01_17_49_17.png

Überprüfen der Funktion des LINE-Bots

Um den Vorgang zu überprüfen, habe ich einige Fotos auf dem LINE-Bot gepostet, den ich dieses Mal erstellt habe. [^ 1] IMG_1528.png

Unabhängig von der Wahrheit des Ergebnisses scheint es als (?) LINE-Bot zu funktionieren.

[^ 1]: Die Fotos, die ich für diesen Beitrag verwendet habe, sind wie folgt. Sonnenblume von Aiko, Thomas & Juliette + Isaac, [Rose von Waldemar Jan](https://www.flickr.com/photos/128905059@ N02 / 22138314909 /), Blumenkohl von Liz West

Recommended Posts

Erstellen Sie eine App für maschinelles Lernen mit ABEJA Platform + LINE Bot
Erstellen Sie mit Minette für Python einen LINE BOT
Erstellen Sie mit Winsows 10 eine maschinelle Lernumgebung von Grund auf neu
Erstellen Sie mit Django einen LINE-Bot
[LINE Messaging API] Erstellen Sie einen BOT, der eine Verbindung zu jemandem mit Python herstellt
So erstellen Sie mit AWS Lambda eine serverlose API für maschinelles Lernen
Eine Geschichte über maschinelles Lernen mit Kyasuket
Erstellen Sie eine GUI-App mit Tkinter of Python
[Python] [LINE Bot] Erstellen Sie einen LINE Bot mit Papageienrückgabe
Erstellen Sie eine einfache Web-App mit Flasche
Ich habe einen Stempelersatzbot mit Linie gemacht
Ich habe einen LINE Bot mit Serverless Framework erstellt!
Schritte zum Erstellen eines Twitter-Bots mit Python
Verfahren zur Erstellung plattformübergreifender Apps mit kivy
Erstellen Sie mit Amazon Lex einen LINE WORKS-Bot
Erstellen Sie eine Python-Umgebung für maschinelles Lernen mit Containern
[Maschinelles Lernen] Erstellen Sie ein Modell für maschinelles Lernen, indem Sie Transferlernen mit Ihrem eigenen Datensatz durchführen
Erstellen Sie einen Slack Bot
[AWS] Ich habe BOT mit LINE WORKS daran erinnert
Erstellen Sie eine Todo-App mit Django REST Framework + Angular
Führen Sie eine Pipeline für maschinelles Lernen mit Cloud Dataflow (Python) aus.
Erstellen Sie mit Py2app und Tkinter eine native GUI-App
Einfaches maschinelles Lernen mit Scikit-Learn und Flask ✕ Web App
Lassen Sie uns eine Todo-App mit dem Django REST-Framework erstellen
Fühlen wir uns wie ein Materialforscher mit maschinellem Lernen
Todo-App mit Django erstellen ③ Aufgabenlistenseite erstellen
Ich habe versucht, LINE BOT mit Python und Heroku zu machen
Erstellen Sie mit Python eine Entwicklungsumgebung für maschinelles Lernen
Todo-App mit Django erstellen ⑤ Funktion zum Bearbeiten von Aufgaben erstellen
[Super einfach] Machen wir einen LINE BOT mit Python.
[LINE Messaging API] Erstellen Sie einen Papageienrückgabe-BOT mit Python
So erstellen Sie schnell eine maschinelle Lernumgebung mit Jupyter Notebook mit UbuntuServer 16.04 LTS
Bis Sie mit Python unter Windows 7 eine maschinelle Lernumgebung erstellen und ausführen
Maschinelles Lernen mit Pokemon gelernt
Erstellen Sie mit GoogleAppEngine / py einen LINE-Bot. Einfache nackte Version
Erstellen Sie mit VirtualBox und Ubuntu eine Scikit-Lernumgebung für maschinelles Lernen
Erstellen Sie einen Mastodon-Bot mit einer Funktion, die automatisch mit Python antwortet
Passende App Ich habe versucht, Statistiken über starke Leute zu erstellen und ein Modell für maschinelles Lernen zu erstellen
Erstellen Sie eine Homepage mit Django
[Lernrekord] Erstelle mit Pyhtons Tkinter ein mysteriöses Dungeon-Spiel
Maschinelles Lernen mit Python! Vorbereitung
Machen Sie einen LINE BOT (Chat)
Bis Django etwas mit einem Linienbot zurückgibt!
Erstellen Sie einen Twitter-BOT mit dem GoogleAppEngine SDK für Python
Maschinelles Lernen Minesweeper mit PyTorch
Erstellen Sie eine maschinelle Lernumgebung
Erstellen einer Todo-App mit Django ① Erstellen Sie eine Umgebung mit Docker
Beginnend mit maschinellem Python-Lernen
Erstellen Sie ein Verzeichnis mit Python
Versuchen Sie es mit Kaggle leicht maschinell
[AWS] Ich habe BOT mit LINE WORKS (Implementierung) in Erinnerung gerufen.
Erstellen Sie eine automatische Klassenverwaltungs-App für Tenho Private Room mit LINE Bot und Python Part 1
Erstellen Sie mit LINE Bot und Python Part 2 eine automatische Klassenverwaltungs-App für Tenho Private Room
Erstellen Sie eine automatische Klassenverwaltungs-App für Tenho Private Room mit LINE Bot und Python Part ③
Schnelle Schritte zum Erstellen einer maschinellen Lernumgebung mit Jupyter Notebook unter macOS Sierra mit anaconda
Eine Geschichte, die mit der Installation der maschinellen Lernbibliothek JAX zusammenhängt
Erstellen einer Windows 7-Umgebung für eine Einführung in das maschinelle Lernen mit Python