[PYTHON] J'ai créé une application Twitter qui identifie et enregistre l'image d'un personnage spécifique sur la chronologie de Twitter par pytorch transfer learning

introduction

J'ai créé une application qui classe automatiquement les images des caractères recommandés dans des dossiers distinctifs.

Cette fois, nous utilisons une bibliothèque d'apprentissage automatique appelée pytorch et une API appelée tweepy qui peut apprendre des informations sur Twitter.

Raison de la création

Il est difficile de voir toute la chronologie de Twitter, je souhaite donc enregistrer uniquement l'image du personnage recommandé Je voulais créer quelque chose en utilisant tweeypy et l'apprentissage automatique Le tutoriel d'apprentissage par transfert de pytorch était merveilleux, j'ai donc voulu l'utiliser. Je voulais faire l'expérience des problèmes qui se posent lors de la création d'une application d'apprentissage automatique.

Ce que j'ai fait

Modification du tutoriel d'apprentissage du transfert de pytorch

Un modèle formé est préparé à l'avance dans Pytorch et il est facile à utiliser. Dans le didacticiel pytorch, je l'ai utilisé et modifié pour l'adapter à la tâche en fonction de la méthode d'apprentissage par transfert. Dans cette tâche, en supposant qu'il existe une image réelle et une image bidimensionnelle sur Twitter, et que l'image bidimensionnelle a une structure d'une image du personnage cible et une image qui ne l'est pas, d'abord l'animation et la réalité J'ai fait un modèle pour identifier l'image, puis j'ai fait un modèle pour identifier à nouveau l'image bidimensionnelle.

Plus précisément, la première méthode utilisée consistait à changer la couche entièrement connectée du res-net18 entraîné en une couche connectée d'une taille adaptée à la classe, et à donner au modèle une image de la tâche pour le recycler.

Dès le début, le taux de discrimination entre les images réelles et non réelles était très élevé, dépassant environ 95% ou plus, mais le taux de discrimination d'un caractère spécifique n'était pas aussi élevé que 70%, et nous avons essayé de l'améliorer par diverses méthodes.

Changements d'algorithme et de modèle

Changement facile

Changement de modèle

La première chose que j'ai essayée a été de changer de modèle. Il existe des modèles entraînés dans pytorch, j'ai donc essayé d'utiliser alex-net parmi eux. Cependant, la précision ne s'est pas améliorée en la changeant simplement, alors je suis retourné à resnet.

Changement de l'algorithme d'optimisation

Au début, nous nous entraînions avec SGD comme algorithme d'optimisation, mais nous avons changé cela et avons décidé d'utiliser Adam. Cependant, ce n'était pas du tout exact, et Adam a entendu dire que les hyperparamètres étaient importants, il a donc décidé d'utiliser optuma, une bibliothèque de recherche d'hyperparamètres.

optuna oputuna est une bibliothèque qui apporte des valeurs numériques de la distribution pour les hyper paramètres que vous souhaitez optimiser. La procédure spécifique consiste à définir d'abord la fonction objectif qui contient la valeur numérique et le para haut que vous souhaitez optimiser.

fonction objective


def objective(trial):

    lr =trial.suggest_loguniform('lr', 1e-6, 1e-4)
    beta1 =trial.suggest_uniform('beta1', 0.8, 0.95)
    beta2 =trial.suggest_uniform('beta2', 0.9, 0.99)
    eps =trial.suggest_loguniform('eps', 1e-9,1e-7)
    gamma = trial.suggest_loguniform('gamma',0.05,0.2)

    model_ft = models.resnet18(pretrained=True)
    num_ftrs = model_ft.fc.in_features
    model_ft.fc = nn.Linear(num_ftrs, 2)
    model_ft = model_ft.to(device)

    criterion = nn.CrossEntropyLoss()

    optimizer_ft = optim.Adam(model_ft.parameters(), lr=lr, betas=(beta1, beta2), eps=eps, weight_decay=0, amsgrad=False)

    exp_lr_scheduler = lr_scheduler.StepLR(optimizer_ft, step_size=7, gamma=gamma)
    model_ft,best_loss,best_acc = train_model(model_ft, criterion, optimizer_ft, exp_lr_scheduler)
    return 1 - best_acc

La mise en garde ici est que lorsque vous renvoyez le nombre que vous souhaitez optimiser, vous devez le définir comme un problème de minimisation. Cette fois, je veux maximiser la précision, donc je soustrais la précision de 1 et renvoie la valeur. Il semble qu'il existe diverses autres fonctions, mais cette fois j'ai appris facilement.

study


study = optuna.create_study()
study.optimize(objective, n_trials=2)

Après avoir défini la fonction objectif, créez un objet d'étude, transmettez-lui la fonction objectif et le nombre d'essais, et les hyper paramètres seront réglés automatiquement.

Lorsque j'ai réglé les hyper paramètres d'Adam ici, il y avait une bonne amélioration de la précision. 77% sur resnet Il y avait une amélioration de 75% sur alex-net.

Changement de données

Ici, j'ai décidé d'adopter une approche telle que l'augmentation de la quantité de données et la modification de la résolution.

Augmenter les données

Premièrement, lorsque nous avons doublé la quantité de données, la précision s'est améliorée à environ 83%. Après cela, lorsque j'ai amélioré la résolution, la précision était d'environ 90%.

Vérification de la validité des résultats du jugement par Guided-Gradcam

Qu'est-ce que Guided-Gradcam?

Je n'entrerai pas dans les détails ici, mais en un mot, c'est une technologie qui visualise où CNN regarde et prend des décisions, en tenant compte de l'influence de chaque classe.

la mise en oeuvre

https://github.com/kazuto1011/grad-cam-pytorch Une méthode telle que gradcam est implémentée ici afin qu'elle puisse être utilisée avec pytorch, et je l'ai implémentée en référence à la démo de ceci.

résultat

image Image lors de l'évaluation comme F Image en jugeant comme T

Implémentation en application

tweepy Une bibliothèque qui englobe les API fournies par Twitter, où vous pouvez apprendre la chronologie et suivre les utilisateurs. Cependant, comme une mise en garde

Il est devenu. Le déroulement de ce processus consiste à apprendre d'abord les tweets sur la chronologie, puis à déterminer celui qui a l'image.

Processus pour déterminer si l'URL a une image


import tweepy
import keys
import classifierImage
def main():
    auth = tweepy.OAuthHandler(keys.consumer_key,keys.consumer_secret)
    auth.set_access_token(keys.access_token,keys.access_token_secret)

    api = tweepy.API(auth)

    public_tweets = api.home_timeline(count=200)
    urls = []
    for tweet in public_tweets:
        if 'media' in tweet.entities:
            for media in tweet.entities['media']:
                #print(media['media_url'])
                urls.append(media['media_url'])
    classifierImage.downloadImage(urls)
            

if __name__=='__main__':
    main()

Ensuite, appelez le modèle entraîné enregistré. Apprenez les données d'image à partir de l'URL de l'argument et convertissez les données binaires en objet Image PIL. Prétraitez-le avec Torchvision, jugez-le avec le modèle et décidez de la destination du téléchargement.

Un programme qui juge et enregistre les images


import urllib.request
import torch
import numpy as np
import io
from PIL import Image
import cv2
from torchvision import transforms,models
import torch.nn as nn

def downloadImage(imageUrls):
    
    tgts=[]
    for url in imageUrls:
        filename = url.split('/')[-1]
        tgt = urllib.request.urlopen(url).read()
        tgts.append((tgt,filename))
    
    toTe = transforms.ToTensor()
    nor = transforms.Normalize([0.5,0.5,0.5],[0.5,0.5,0.5])
    
    co = transforms.Compose([
        transforms.Resize(512),
        transforms.CenterCrop(448),
        transforms.ToTensor(),
        transforms.Normalize([0.5,0.5,0.5],[0.5,0.5,0.5])
        ])
    
    #tensors = torch.cat(tgs,dim=0)
    
    classfier_anime_model = models.resnet18(pretrained=True)
    num_ftrs = classfier_anime_model.fc.in_features

    classfier_anime_model.fc = nn.Linear(num_ftrs, 2)
    classfier_anime_model.load_state_dict(torch.load('classfierAnime'))
    classfier_anime_model.eval()

    classfier_Koishi_model = models.resnet18(pretrained=True)
    num_ftrs_k = classfier_Koishi_model.fc.in_features

    classfier_Koishi_model.fc = nn.Linear(num_ftrs_k, 2)
    classfier_Koishi_model.load_state_dict(torch.load('classfierKoishi1'))
    classfier_Koishi_model.eval()

    with torch.no_grad():
        for i,tg in enumerate(tgts):
            t = Image.open(io.BytesIO(tg[0])).convert('RGB')
            print(t)
            t = co(t)
            t = t.unsqueeze(0)
            
            out = classfier_anime_model(t)
            _,preds = torch.max(out,1)
            print(out)

            if preds[0]==1:
                out_k = classfier_Koishi_model(t)
                _,preds_k = torch.max(out_k,1)
                if preds_k[0]==0:
                    with open("img/"+tg[1], mode='wb') as f:
                        f.write(tg[0])
                else:
                    with open("imgKoishi/"+tg[1], mode='wb') as f:
                        f.write(tg[0])

            else:
                with open("realImg/"+tg[1], mode='wb') as f:
                    f.write(tg[0])

Le résultat de l'utilisation effective de l'application

Résultats obtenus en déplaçant réellement

Le taux d'identification pour savoir s'il s'agissait d'une image réelle était très bon et satisfaisant. Il n'y a pratiquement pas eu d'oubli pour déterminer s'il y avait un caractère spécifique, mais bon nombre des éléments jugés vrais ne remplissaient pas les conditions. (Le rappel coûte cher, mais Pressision l'est autant) Il est probable que la cause de ceci est que les images enregistrées sont biaisées et que l'identification des images qui ne remplissent pas les conditions qui n'ont pas été enregistrées n'a pas réussi. Un autre problème qui s'est produit était que l'image du personnage cible n'apparaissait pas sur la chronologie au début, donc j'étais confus parce que je ne pouvais pas juger s'il pouvait être identifié. Grâce à une telle opération réelle, il était bon de constater que des données non apprises empêchent l'identification.

Ce que je veux faire dans le futur

――Je veux pouvoir l'enregistrer régulièrement, mais je ne peux pas laisser mon ordinateur personnel allumé, donc je veux pouvoir le traiter avec une tarte aux framboises. --Je souhaite pouvoir mettre à jour automatiquement le modèle à l'aide de l'image enregistrée.

Site référencé

https://www.slideshare.net/takahirokubo7792/ss-71453093 https://qiita.com/koki-sato/items/c16c8e3445287698b3a8 http://docs.tweepy.org/en/v3.5.0/index.html https://pytorch.org/tutorials/beginner/transfer_learning_tutorial.html https://qiita.com/enmaru/items/2770df602dd7778d4ce6

Recommended Posts

J'ai créé une application Twitter qui identifie et enregistre l'image d'un personnage spécifique sur la chronologie de Twitter par pytorch transfer learning
J'ai essayé de créer un script qui retrace les tweets d'un utilisateur spécifique sur Twitter et enregistre l'image publiée à la fois
J'ai créé une application Twitter qui décrypte les caractères de pré-connexion avec heroku (échec)
J'ai refactoré "J'ai essayé de faire un script qui enregistre les images postées à la fois en retournant sur les tweets d'un utilisateur spécifique sur Twitter".
J'ai créé un robot Line qui devine le sexe et l'âge d'une personne à partir de l'image
J'ai fait une image ponctuelle de l'image d'Irasutoya. (partie 1)
J'ai fait une image ponctuelle de l'image d'Irasutoya. (partie 2)
pandas Récupère le nom d'une colonne contenant un caractère spécifique
J'ai créé un robot Twitter qui marmonne le Pokémon capturé par #PokemonGO
J'ai fait un bot mou qui m'informe de la température
J'ai vérifié l'image de l'Université des sciences sur Twitter avec Word2Vec.
[Python] J'ai analysé le journal d'un homme au cours de sa première année de vie professionnelle et j'ai fait un jugement positif / négatif sur la vie professionnelle.
J'ai fait un calendrier qui met à jour automatiquement le calendrier de distribution de Vtuber
J'ai fait GAN avec Keras, donc j'ai fait une vidéo du processus d'apprentissage.
[Python] J'ai créé un code de scraping web qui acquiert automatiquement le titre de l'actualité et l'URL de Nihon Keizai Shimbun.
J'ai créé un LINE BOT qui renvoie une image de riz terroriste en utilisant l'API Flickr
J'ai créé une commande appdo pour exécuter des commandes dans le contexte de l'application
Avec LINEBot, j'ai fait une application qui m'informe de "l'heure du bus"
J'ai créé un Linebot qui m'informe des sites d'évacuation à proximité sur AWS
Mise en place d'un modèle de prédiction des taux de change (taux dollar-yen) par machine learning
J'ai créé et publié une image Docker qui lit RSS et tweete automatiquement régulièrement.
[Python / C] J'ai créé un appareil qui fait défiler sans fil l'écran d'un PC à distance.
J'ai fait un calendrier qui met à jour automatiquement le calendrier de distribution de Vtuber (édition Google Calendar)
#Une fonction qui renvoie le code de caractère d'une chaîne de caractères
Une bibliothèque qui surveille la vie et la mort d'autres machines en envoyant un ping à partir de Python
Une méthode concrète pour prédire les courses de chevaux et simuler le taux de récupération par apprentissage automatique
Un exemple de mécanisme qui renvoie une prédiction par HTTP à partir du résultat de l'apprentissage automatique
J'ai essayé de vérifier la classification yin et yang des membres hololive par apprentissage automatique
J'ai créé une API avec Docker qui renvoie la valeur prédite du modèle d'apprentissage automatique
J'ai créé une fonction pour découper l'image de python openCV, alors veuillez l'utiliser.
TensorFlow change-t-il l'image de l'apprentissage profond? Ce que j'ai pensé après avoir touché un peu