Verwenden der Facebook Messenger API Ich habe einen Bot implementiert, der mir ähnliche AV-Schauspielerinnen mitteilt, wenn ich ein Bild hochlade.
Der Server, der die Bot-Antwort ausführt, wird aus verschiedenen Gründen mit "Go" erstellt, die Bildunterscheidung wird mit "Python" erstellt (die Gesichtserkennung ist "OpenCV" und das Faltungsnetzwerk für die Klassifizierung ist "TensorFlow"). Die I / F zwischen den Sprachen ist "gRPC", und RPC wird von "Gehe zu Python" ausgeführt.
Ein Worker-Prozess, der einen Webhook von Facebook Messenger empfängt und eine Bot-Antwort gibt.
Messenger Bot Server Gin wird für den Webserver verwendet. Es ist nicht besonders schwierig, aber wenn der Datenverkehr zunimmt, scheinen Nachrichten von mehreren Benutzern gemeinsam an den Webhook gesendet zu werden. Wenn Sie es in einem Unternehmen verwenden, müssen Sie vorsichtig sein. Bitte verzeihen Sie, dass die Fehlerbehandlung süß ist.
const (
PORT = ":3000"
VERIFICATION_TOKEN = "{{YOUR_VERIFICATION_TOKEN}}"
ENDPOINT_URL = "https://graph.facebook.com/v2.6/me/messages"
)
func main() {
router := gin.Default()
router.GET("/messenger", varifyToken)
router.POST("/messenger", processMessages)
router.Run(PORT)
}
func varifyToken(c *gin.Context) {
token := c.Query("hub.verify_token")
challenge := c.Query("hub.challenge")
if token == VERIFICATION_TOKEN {
c.String(http.StatusOK, challenge + "\n")
} else {
log.WithFields(log.Fields{
"received": token,
"expected": VERIFICATION_TOKEN,
}).Warn("Invalid token.")
}
}
func processMessages(c *gin.Context) {
var json model.Webhook
if c.BindJSON(&json) == nil {
for _, e := range json.Entry {
for _, m := range e.Messaging {
respondToOneMessage(&m)
}
}
c.JSON(http.StatusOK, gin.H{"status": "you are logged in"})
}
}
func respondToOneMessage(m *model.Messaging) {
sender := m.Sender.Id
switch {
// Receive Text
case m.Message.Text != "":
// Receive Image
case m.Message.Attachments[0].Type == "image":
url := m.Message.Attachments[0].Payload.Url
path := util.SaveImg(url)
rs, err := classifyImg(path)
if err != nil {
log.Fatal(err)
}
txt := fmt.Sprintf("Die Person auf dem Foto%Ähnlichkeit mit s%f%%ist.", rs.Result[0].Label, rs.Result[0].Accuracy * 100)
err2 := sendTextMessage(sender, txt)
if err2 != nil {
log.Fatal(err2)
}
default:
log.Error("Unexpected Message")
}
}
func sendTextMessage(recipient int64, text string) error {
endpoint := fmt.Sprintf("%s?%s=%s", ENDPOINT_URL, "access_token", VERIFICATION_TOKEN)
json := `{"recipient":{"id":%d},"message":{"text":"%s"}}`
body := fmt.Sprintf(json, recipient, text)
req, err := http.NewRequest(
"POST",
endpoint,
strings.NewReader(body),
)
if err != nil {
return err
}
req.Header.Set("Content-Type", "application/json")
client := &http.Client{ Timeout: time.Duration(3 * time.Second) }
resp, err := client.Do(req)
log.Printf("requested")
defer resp.Body.Close()
return err
}
Unter Berücksichtigung des Bildweges wird das Gesicht erkannt und das trainierte Faltungs-Neuronale Netz bestimmt die Ähnlichkeit des Gesichts.
Nun, das Bild, das ich bekommen habe, egal wie tief es lernt, selbst wenn es von CNN so klassifiziert wird, wie es ist, wird es nicht sehr genau sein, also schneiden Sie zuerst nur das Gesichtsteil. Dieses Mal habe ich "OpenCV" zur Erkennung verwendet. Nimmt ein Array im NumPy-Format als Argument und gibt das Ergebnis des Zuschneidens nur des Gesichtsteils zurück. Es gab auch ein Horrorbild, in dem das rechte Ohr aus irgendeinem Grund als Gesicht erkannt wurde. Ich habe ein wenig Angst, weil es psychische Fotos zu erkennen scheint.
def face_detect(img):
face_cascade = cv2.CascadeClassifier('./haarcascade_frontalface_default.xml')
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
faces = face_cascade.detectMultiScale(
gray,
scaleFactor=1.1,
minNeighbors=5,
minSize=(30, 30),
flags = cv2.CASCADE_SCALE_IMAGE
)
if len(faces) > 0:
fc = faces[0]
x = fc[0]
y = fc[1]
w = fc[2]
h = fc[3]
return img[y:y+h, x:x+w]
else:
return None
Ich dachte, es wäre ziemlich schwierig, aber das war's. Ich war überrascht, weil es zu bequem war. Ich werde den Algorithmus dieses Mal richtig studieren.
Trainieren Sie Netzwerkgewichte mit gesammelten und vorverarbeiteten Bildern.
Die Struktur des Faltungs-Neuronalen Netzes ist Deep MNIST for Experts. das Gleiche,
Es ist 6 Schichten.
Ich weiß nicht, wie ich TensorFlow nur mit dem Tutorial verwenden soll. Lesen Sie daher TensorFlow Mechanics 101 sorgfältig durch. Ist empfohlen.
Der Modellierungsteil ist ein Auszug.
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import sys
import cv2
import numpy as np
import tensorflow as tf
NUM_CLASSES = 5
IMAGE_SIZE = 28
class CNNetwork:
def inference(self, x_images, keep_prob):
def weight_variable(shape):
initial = tf.truncated_normal(shape, stddev=0.1)
return tf.Variable(initial)
def bias_variable(shape):
initial = tf.constant(0.1, shape=shape)
return tf.Variable(initial)
def conv2d(x, W):
return tf.nn.conv2d(x, W, strides=[1, 1, 1, 1], padding='SAME')
def max_pool_2x2(x):
return tf.nn.max_pool(x, ksize=[1, 2, 2, 1],
strides=[1, 2, 2, 1], padding='SAME')
with tf.name_scope('conv1') as scope:
W_conv1 = weight_variable([5, 5, 3, 32])
b_conv1 = bias_variable([32])
h_conv1 = tf.nn.relu(tf.nn.bias_add(conv2d(x_images, W_conv1), b_conv1))
with tf.name_scope('pool1') as scope:
h_pool1 = max_pool_2x2(h_conv1)
with tf.name_scope('conv2') as scope:
W_conv2 = weight_variable([5, 5, 32, 64])
b_conv2 = bias_variable([64])
h_conv2 = tf.nn.relu(tf.nn.bias_add(conv2d(h_pool1, W_conv2), b_conv2))
with tf.name_scope('pool2') as scope:
h_pool2 = max_pool_2x2(h_conv2)
with tf.name_scope('fc1') as scope:
W_fc1 = weight_variable([7*7*64, 1024])
b_fc1 = bias_variable([1024])
h_pool2_flat = tf.reshape(h_pool2, [-1, 7*7*64])
h_fc1 = tf.nn.relu(tf.nn.bias_add(tf.matmul(h_pool2_flat, W_fc1), b_fc1))
h_fc1_drop = tf.nn.dropout(h_fc1, keep_prob)
with tf.name_scope('fc2') as scope:
W_fc2 = weight_variable([1024, NUM_CLASSES])
b_fc2 = bias_variable([NUM_CLASSES])
with tf.name_scope('softmax') as scope:
y_conv=tf.nn.softmax(tf.nn.bias_add(tf.matmul(h_fc1_drop, W_fc2), b_fc2))
return y_conv
Zum Zeitpunkt des Trainings führt das Speichern des Gewichts des Trainings zu einer Binärdatei wie folgt: Es kann verwendet werden, wenn die Klassifizierungsfunktion von RPC aufgerufen wird.
saver = tf.train.Saver()
save_path = saver.save(sess, "model.ckpt")
Dies ist eine Klassifizierungsfunktion, die das Ausführungsergebnis der Softmax-Funktion auf der tiefsten Ebene des Netzwerks zurückgibt.
def classify(self, image_path):
try:
img = cv2.imread(image_path)
img = face_detect(img)
img = cv2.resize(img, (IMAGE_SIZE, IMAGE_SIZE))
img = img.astype(np.float32)/255.0
images_placeholder = tf.placeholder("float", shape=(None, IMAGE_SIZE, IMAGE_SIZE, 3))
labels_placeholder = tf.placeholder("float", shape=(None, NUM_CLASSES))
keep_prob = tf.placeholder("float")
logits = self.inference(images_placeholder, keep_prob)
sess = tf.InteractiveSession()
saver = tf.train.Saver()
sess.run(tf.initialize_all_variables())
saver.restore(sess, "./model.ckpt")
pred = logits.eval(feed_dict={images_placeholder: [img],keep_prob: 1.0 })[0]
return pred
except Exception as e:
print 'message:' + e.message
gRPC Schließlich RPC TensorFlow vom Bot-Server in Go-Sprache implementiert. gRPC verwendet Protokollpuffer als Datenformat. Grob gesagt handelt es sich um eine universelle Datendefinition für die Kommunikation zwischen Programmen. Wenn Sie eine .proto-Datei erstellen, die eine Definitionsdatei ist, können Sie mit einem Befehl eine Bibliothek zum Serialisieren / Deserialisieren für jede Sprache generieren.
Erstellen Sie zunächst eine "Proto" -Datei, die die Datenstruktur wie unten gezeigt definiert.
cnn.proto
syntax = "proto3";
package cnn;
service Classifier {
rpc classify (CnnRequest) returns (CnnResponse){}
}
message CnnRequest {
string filepath = 1;
}
message CnnResponse {
repeated Result result = 1;
}
message Result {
string label = 1;
double accuracy = 2;
}
Erstellen Sie nach Abschluss der Definition Bibliotheksdateien für jede Sprache von Go und Python.
# go
protoc --go_out=plugins=grpc:./ cnn.proto
# Python
protoc --python_out=. --grpc_out=. --plugin=protoc-gen-grpc=`which grpc_python_plugin` cnn.proto
Damit werden Bibliotheken für jede Sprache, "cnn.pb.go" und "cnn_pb2.py", generiert.
Implementieren Sie den gRPC-Server mithilfe der generierten Bibliothek.
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import time
import cnn_pb2 as pb
import cnn
_ONE_DAY_IN_SECONDS = 60 * 60 * 24
class Classier(pb.BetaClassifierServicer):
def classify(self, request, context):
path = request.filepath
print path
n = cnn.CNNetwork()
accuracies = n.classify(path)
print accuracies
labels = ['Kaho Shibuya', 'AIKA', 'Aki Sasaki', 'Ai Uehara', 'Ayumi Shinoda']
nameWithAccuracy = []
for i in range (0, len(labels)):
nameWithAccuracy.append((accuracies[i], labels[i]))
nameWithAccuracy.sort(reverse=True)
response = pb.CnnResponse()
try:
#Geben Sie vorerst die drei besten Personen zurück
for i in range(0, 3):
r = pb.Result()
label = nameWithAccuracy[i][1]
accuracy = float(nameWithAccuracy[i][0])
response.result.add(label=label, accuracy=accuracy)
except Exception as e:
print e.message
return response
def serve():
server = pb.beta_create_Classifier_server(Classier())
server.add_insecure_port('[::]:50051')
server.start()
try:
while True:
time.sleep(_ONE_DAY_IN_SECONDS)
except KeyboardInterrupt:
server.stop(0)
if __name__ == '__main__':
serve()
Als nächstes implementieren wir den gRPC-Client in der Sprache Go.
//Auszug
func classifyImg(filepath string) (*cnn.CnnResponse, error) {
address := "localhost:50051"
conn, err := grpc.Dial(address, grpc.WithInsecure())
if err != nil {
log.Fatalf("did not connect: %v", err)
}
defer conn.Close()
c := cnn.NewClassifierClient(conn)
result, err := c.Classify(context.Background(), &cnn.CnnRequest{Filepath: filepath})
if err != nil {
log.Fatalf("couldn't classify: %v", err)
return nil, err
}
return result, nil
}
Technisch gesehen war das Erstellen von OpenCV unter Amazon Linux am aufwändigsten als das Programmieren. Die Unterscheidungsgenauigkeit des Faltungs-Neuronalen Netzes unter Verwendung der Testdaten betrug 79%. Wenn es sich um ein Bild handelt, das wie die Aufnahme zu Beginn von vorne aufgenommen wurde, ist die Beurteilungsgenauigkeit jedoch relativ hoch Ich konnte das Bild des Ausdrucks nicht unterscheiden wie Teruhide, der weinte.
[Lineare Algebra für die Programmierung](http://www.amazon.co.jp/%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83% 9F% E3% 83% B3% E3% 82% B0% E3% 81% AE% E3% 81% 9F% E3% 82% 81% E3% 81% AE% E7% B7% 9A% E5% BD% A2% E4% BB% A3% E6% 95% B0-% E5% B9% B3% E5% B2% A1-% E5% 92% 8C% E5% B9% B8 / dp / 4274065782) Ich kannte die Grundlagen der linearen Algebra überhaupt nicht und lernte von Grund auf.
[Deep Learning (Machine Learning Professional Series)](https://www.amazon.co.jp/%E6%B7%B1%E5%B1%A4%E5%AD%A6%E7%BF%92-%E6 % A9% 9F% E6% A2% B0% E5% AD% A6% E7% BF% 92% E3% 83% 97% E3% 83% AD% E3% 83% 95% E3% 82% A7% E3% 83 % 83% E3% 82% B7% E3% 83% A7% E3% 83% 8A% E3% 83% AB% E3% 82% B7% E3% 83% AA% E3% 83% BC% E3% 82% BA -% E5% B2% A1% E8% B0% B7% E8% B2% B4% E4% B9% 8B-ebook / dp / B018K6C99A? Ie = UTF8 & btkr = 1 & ref_ = dp-kindle-redirect) Da die Entwicklung der Formel sehr detailliert geschrieben ist, konnte ich sie in letzter Minute lesen.
Identifizieren Sie die Anime Yuruyuri Produktionsfirma mit TensorFlow Für die Implementierung des Faltungs-Neuronalen Netzes habe ich darauf hingewiesen, was sorgfältig erklärt wird.
Recommended Posts