(◎◎) {Laissons Python faire les choses ennuyeuses) ......... (Hé? Laissons Python faire les devoirs} (゜) (゜)

Avez-vous laissé Python faire les choses ennuyeuses?

Je ne t'ai pas laissé faire

Un livre sur la couverture d'un robot comme ce C-3PO sur l'herbe

image.png

Il est réputé comme un bon livre de Python, et de nombreuses personnes l'ont peut-être lu.

Alors, est-ce que quelqu'un a lu ce livre et a fait faire à Python quelque chose de vraiment ennuyeux? N'est-ce pas assez petit? Je pense qu'il y a beaucoup de gens qui sont satisfaits de la lecture. J'étais l'un des leurs. Je ne l'ai lu qu'une fois il y a environ un an. .. .. était

La formation en IA a commencé

Récemment, l'IA est devenue un buzz. Il semble que diverses entreprises commencent à introduire l'IA. L'entreprise pour laquelle je travaille ne fait pas exception, et j'ai commencé à introduire une formation en IA.

Au cours de la formation, j'ai eu la tâche de créer moi-même un modèle d'apprentissage automatique et de prédire les caractères manuscrits.

Flux de défi

image.png

1. Modélisation

Définit un modèle d'apprentissage en profondeur. Combien de couches d'apprentissage en profondeur devraient être utilisées ici et combien de nœuds devraient être utilisés dans chaque couche? Nous ferons la configuration générale et le réglage fin du modèle.

2. Apprentissage

Entraînez le modèle en transmettant des données (données d'apprentissage) dans lesquelles l'étiquette correcte et l'image des caractères manuscrits sont associées. Ici, vous pouvez mesurer le résultat de la prédiction provisoire en utilisant une partie des données d'entraînement comme données de vérification (voir 3. Prédiction). Nous utiliserons le modèle avec le résultat de prédiction provisoire le plus élevé pour les travaux suivants.

3. Prédiction:

Prédisez les caractères manuscrits en transmettant des données (données de vérification) uniquement pour les images de caractères manuscrits. La prévision est sortie sous forme de fichier CSV.

4. Soumission:

Téléchargez le fichier CSV de prédiction sur le serveur Web préparé par la société de formation via un navigateur.

5. Reçu des résultats:

La précision du résultat de la prédiction est affichée sur le serveur Web.

Le défi était d'obtenir l'exactitude de la note de passage en répétant les étapes 1 à 5 ci-dessus.

Jeu de travail

Après l'avoir répété plusieurs fois, j'en suis venu à penser que c'était un travail de routine. Une fois que le contour du modèle est décidé, tout ce que vous avez à faire est d'ajuster les paramètres du modèle et de répéter l'apprentissage-> prédiction → soumission. De plus, le temps d'attente est très long! !! Je suis venu me demander si cela pouvait être automatisé.

Let's automation with python

Laissons Python faire les choses ennuyeuses.

Organisez à nouveau le flux des problèmes

image.png

Modélisation / Formation / Prédiction

Cela se fait dans un environnement d'exécution Python interactif appelé notebook Jupyter. Je pensais que l'automatisation pouvait être réalisée en transformant le code écrit dans le notebook Jupyter en une classe / fonction python et en passant les paramètres utilisés pour le régler comme argument.

Comment convertir le code du notebook Jupyter en fichier Python https://qiita.com/abts/items/25bb611b6d83e646abdd

Soumission des résultats / réception des résultats

Téléchargez la sortie du fichier CSV par prédiction sur le site de téléchargement via google chrome. Il semble que le navigateur Web puisse être automatisé en utilisant une bibliothèque Python appelée Selenium.

À propos de Selenium https://qiita.com/Chanmoro/items/9a3c86bb465c1cce738a

Contrainte: seuls 5 fichiers peuvent être téléchargés par jour

Il y avait une limite selon laquelle vous ne pouvez importer que jusqu'à 5 fichiers CSV prévus par jour. Sans cela, il aurait été plus facile de simplement parcourir le processus ci-dessus. .. .. Il semble que nous devons concevoir ici.

Flux d'automatisation

image.png

Ce que font les humains

--Définissez des dizaines / centaines d'ensembles de paramètres à transmettre au modèle dans le fichier JSON à l'avance. ――Regardez les dessins animés et YouTube jusqu'à ce que tous les paramètres passés soient traités. ――Après avoir tout terminé, vérifiez le résultat, terminez si vous avez atteint l'objectif et réfléchissez au paramètre suivant en fonction du résultat

Python ce que vous faites

Modélisation / Formation / Prédiction

C'est un processus en boucle.

--Obtenir les paramètres à utiliser pour le modèle à partir du fichier JSON --La modélisation --Apprentissage (la précision de prédiction temporaire calculée à ce moment est stockée au format CSV) --Prédiction (un résultat CSV est créé pour chaque boucle)

Soumission / réception des résultats

Il fait une boucle une fois par jour, seulement 5 fois après minuit. Cinq fois, c'est le nombre maximum de soumissions par jour.

Implémentation (codage)

avant ça

Comme prévu, le site de téléchargement de la société de formation ne peut pas être publié, donc cette fois, nous utiliserons plutôt le système de reconnaissance de chiffres de kaggle. Le flux de base ne change pas. De plus, kaggle a une API pour le téléchargement, mais ne vous y trompez pas cette fois (-_-) J'espère que vous pouvez voir cela comme une reproduction.

Expliquons brièvement le code réellement utilisé.

code

Cours d'apprentissage automatique

ai.py


from itertools import product
import os

import pandas as pd
import numpy as np

np.random.seed(2)

from keras.utils.np_utils import to_categorical  # convert to one-hot-encoding
from keras.models import Sequential
from keras.layers import Dense, Dropout, Flatten, Conv2D, MaxPool2D
from keras.optimizers import RMSprop
from keras.preprocessing.image import ImageDataGenerator
from keras.callbacks import ReduceLROnPlateau
from sklearn.model_selection import train_test_split


class MnistModel(object):
    def __init__(self, train_data_name='train.csv', test_data_csv='test.csv'):
        input_dir = self.get_dir_path('input')
        train_data_path = os.path.join(input_dir, train_data_name)
        test_data_path = os.path.join(input_dir, test_data_csv)
        #Load the data
        self.train = pd.read_csv(train_data_path)
        self.test = pd.read_csv(test_data_path)

    def get_dir_path(self, dir_name):
        """ Function to directory path

        Params:
            dir_name(str): The name of directory
        Return:
            str: The directory path

        """
        base_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
        data_directory = os.path.join(base_dir, dir_name)
        return data_directory


    def learning_and_predict(self, csv_file_path, config):
        label = self.train["label"]
        train = self.train.drop(labels=["label"], axis=1)


        # Normalize the data
        train = train / 255.0
        test = self.test / 255.0

        # Reshape image in 3 dimensions (height = 28px, width = 28px , canal = 1)
        train = train.values.reshape(-1, 28, 28, 1)
        test = test.values.reshape(-1, 28, 28, 1)

        # Encode labels to one hot vectors (ex : 2 -> [0,0,1,0,0,0,0,0,0,0])
        label = to_categorical(label, num_classes=10)

        # Set the random seed
        random_seed = 2

        # Split the train and the validation set for the fitting
        X_train, X_val, Y_train, Y_val = train_test_split(train, label, test_size=0.1, random_state=random_seed)

        model = Sequential()
        model.add(Conv2D(filters=32, kernel_size=(5, 5), padding='Same',
                              activation='relu', input_shape=(28, 28, 1)))
        model.add(Conv2D(filters=32, kernel_size=(5, 5), padding='Same',
                              activation='relu'))
        model.add(MaxPool2D(pool_size=(2, 2)))
        model.add(Dropout(0.25))
        model.add(Conv2D(filters=64, kernel_size=(3, 3), padding='Same',
                              activation='relu'))
        model.add(Conv2D(filters=64, kernel_size=(3, 3), padding='Same',
                              activation='relu'))
        model.add(MaxPool2D(pool_size=(2, 2), strides=(2, 2)))
        model.add(Dropout(0.25))
        model.add(Flatten())
        model.add(Dense(256, activation="relu"))
        model.add(Dropout(0.5))
        model.add(Dense(10, activation="softmax"))

        optimizer = RMSprop(lr=0.001, rho=0.9, epsilon=1e-08, decay=0.0)
        model.compile(optimizer=optimizer, loss="categorical_crossentropy", metrics=["accuracy"])

        datagen = ImageDataGenerator(
            featurewise_center=False,  # set input mean to 0 over the dataset
            samplewise_center=False,  # set each sample mean to 0
            featurewise_std_normalization=False,  # divide inputs by std of the dataset
            samplewise_std_normalization=False,  # divide each input by its std
            zca_whitening=False,  # apply ZCA whitening
            rotation_range=config['ROTATION_RANGE'],  # randomly rotate images in the range (degrees, 0 to 180)
            zoom_range=config['ZOOM_RANGE'],  # Randomly zoom image
            width_shift_range=config['WIDTH_SHIFT_RANGE'],  # randomly shift images horizontally (fraction of total width)
            height_shift_range=config['HEIGHT_SHIFT_RANGE'],  # randomly shift images vertically (fraction of total height)
            horizontal_flip=False,  # randomly flip images
            vertical_flip=False)  # randomly flip images
        datagen.fit(X_train)

        learning_rate_reduction = ReduceLROnPlateau(
                                                    monitor='val_acc',
                                                    patience=3,
                                                    verbose=1,
                                                    factor=0.5,
                                                    min_lr=0.00001
        )

        epochs = 1
        batch_size = 86

        history = model.fit_generator(
            datagen.flow(
                X_train,
                Y_train,
                batch_size=batch_size
            ),
            epochs=epochs,
            validation_data=(
                X_val,
                Y_val
            ),
            verbose=2,
            steps_per_epoch=X_train.shape[0] // batch_size,
            callbacks=[learning_rate_reduction])

        results = model.predict(test)
        results = np.argmax(results, axis=1)
        results = pd.Series(results, name="Label")
        submission = pd.concat([pd.Series(range(1, 28001), name="ImageId"), results], axis=1)
        submission.to_csv(csv_file_path, index=False)

        return history.history['val_acc'][0]


Le modèle de cet apprentissage automatique a été créé en se référant à ce qui suit (pakuri rond). https://www.kaggle.com/yassineghouzam/introduction-to-cnn-keras-0-997-top-6

Utilisez la méthode learning_and_predict pour créer / apprendre / prédire tous les modèles. config sera une liste de paramètres.

datagen = ImageDataGenerator(
....
    rotation_range=config['ROTATION_RANGE'],  # randomly rotate images in the range (degrees, 0 to 180)
    zoom_range=config['ZOOM_RANGE'],  # Randomly zoom image
    width_shift_range=config['WIDTH_SHIFT_RANGE'],  # randomly shift images horizontally (fraction of total width)
    height_shift_range=config['HEIGHT_SHIFT_RANGE'],  # randomly shift images vertically (fraction of total height)
....
        datagen.fit(X_train)

Cette fois, les paramètres de Image Data Generator sont réglés.

Définition des paramètres JSON

{
    "CONFIG": [
        {
        "ROTATION_RANGE": 10,
        "ZOOM_RANGE": 0.1,
        "WIDTH_SHIFT_RANGE": 0.1,
        "HEIGHT_SHIFT_RANGE": 0.1
        },
        {
        "ROTATION_RANGE": 10,
        "ZOOM_RANGE": 0.1,
        "WIDTH_SHIFT_RANGE": 0.1,
        "HEIGHT_SHIFT_RANGE": 0.2
        },
        {
        "ROTATION_RANGE": 10,
        "ZOOM_RANGE": 0.1,
        "WIDTH_SHIFT_RANGE": 0.1,
        "HEIGHT_SHIFT_RANGE": 0.3
        },
        {
        "ROTATION_RANGE": 10,
        "ZOOM_RANGE": 0.1,
        "WIDTH_SHIFT_RANGE": 0.1,
        "HEIGHT_SHIFT_RANGE": 0.4
        }
    ]
}

Classe de téléchargement Web

Il s'agit d'une classe permettant de télécharger du CSV prédictif sur un site Web. Il est principalement mis en œuvre dans le sélénium.

import os
import time
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC


DRIVER_FILE_PATH = 'C:\Drivers\chromedriver_win32\chromedriver.exe'
DRIVER_FILE_NAME = 'chromedriver'
TIMEOUT = 30


class BaseBrowserOperator(object):
    """ Base model of browser operator """
    def __init__(self, headless = False):
        driver_path = os.path.join(os.path.dirname(DRIVER_FILE_PATH), DRIVER_FILE_NAME)
        if headless == True:
            options = webdriver.ChromeOptions()
            options.add_argument('--headless')
            self.browser = webdriver.Chrome(driver_path, options=options)
        else:
            self.browser = webdriver.Chrome(driver_path)

    def __del__(self):
        self.browser.close()


class BrowserOperator(BaseBrowserOperator):
    """ The browser operator model """
    def go_to_page(self, url):
        """ Function to go to a page

        Params:
            url(str): The url of page
        """
        self.browser.get(url)

    def click(self, element_xpath, wait=True):
        """ Function to click the page's element

        TODO:
            implement finding element method other than xpath

        Params:
            element_xpath(str): The xpath of element be clicked
            wait(boolean): If disable waiting, please give False.
        """
        if wait:
            self.wait_element(element_xpath)
        self.browser.find_element_by_xpath(element_xpath).click()

    def input_value(self, element_xpath, value, wait=True):
        """ Function to input value to page's element

        TODO:
            implement finding element method other than xpath

        Params:
            element_xpath(str): The xpath of element be clicked
            value(str): The value be inputed
            wait(boolean): If disable waiting, please give False.
        """
        if wait:
            self.wait_element(element_xpath)
        self.browser.find_element_by_xpath(element_xpath).send_keys(value)

    def get_value(self, element_xpath, wait=True):
        """ Function to get value from page's element

        Params:
            element_xpath(str): The xpath of element be clicked
            wait(boolean): If disable waiting, please give False.
        Returns:
            str: Value from page's element
        """
        if wait:
            self.wait_element(element_xpath)
        return self.browser.find_element_by_xpath(element_xpath).text

    def import_cookies(self):
        """ Function to import cookie informations """
        cookies = self.browser.get_cookies()
        for cookie in cookies:
            self.browser.add_cookie({
                'name': cookie['name'],
                'value': cookie['value'],
                'domain': cookie['domain'],
            })

    def wait_element(self, element_xpath):
        """ Function to wait to appear element on page

        TODO:
            implement finding element method other than xpath

        Params:
            element_xpath(str): The xpath of element be used to wait
        """
        WebDriverWait(self.browser, TIMEOUT).until(EC.element_to_be_clickable((By.XPATH, element_xpath)))

    def wait_value(self, element_xpath, value, timeout=300):
        """ Function to wait until element's value equal the specific value

        Params:
            element_xpath(str): The xpath of element be used for wait
            value(str): The used value for wait
            timeout(int): The waiting timeout(sec)
        """
        state = ''
        sec = 0
        while not state == value:
            state = self.browser.find_element_by_xpath(element_xpath).text
            time.sleep(1)
            if sec > timeout:
                raise TimeoutError("Timeout!! The value wasn't available")
            sec += 1


Utilisez chaque méthode comme suit.

Vous pouvez télécharger le fichier CSV prédit avec kaggle avec le code suivant.

    def upload_csv_to_kaggle(self, file_path):
        """ Function to upload csv file to kaggle

        Params:
            file_path(str): The path of csv file uploaded
        """
        uploader = BrowserOperator()
        #Transition vers la page kaggle
        uploader.go_to_page(
            'https://www.kaggle.com/c/digit-recognizer'
        )
        #Cliquez sur le bouton Se connecter
        uploader.click(
            '/html/body/main/div[1]/div/div[1]/div[2]/div[2]/div[1]/a/div/button'
        )
        #Cliquez sur Se connecter avec google
        uploader.click(
            '/html/body/main/div/div[1]/div/form/div[2]/div/div[1]/a/li/span'
        )
        #Entrez votre adresse email
        uploader.input_value(
            '/html/body/div[1]/div[1]/div[2]/div/div[2]/div/div/div[2]/div/div[1]/div/form/span/section/div/div/div[1]/div/div[1]/div/div[1]/input',
            GOOGLE_MAILADDRESS
        )
        uploader.click(
            '/html/body/div[1]/div[1]/div[2]/div/div[2]/div/div/div[2]/div/div[2]/div/div[1]/div'
        )
        #Entrer le mot de passe
        uploader.input_value(
            '/html/body/div[1]/div[1]/div[2]/div/div[2]/div/div/div[2]/div/div[1]/div/form/span/section/div/div/div[1]/div[1]/div/div/div/div/div[1]/div/div[1]/input',
            GOOGLE_PASSWORD
        )
        uploader.click(
            '/html/body/div[1]/div[1]/div[2]/div/div[2]/div/div/div[2]/div/div[2]/div/div[1]/div/span/span'
        )
        time.sleep(10) #Ça n'a pas marché sans dormir
     #Importer des cookies
        uploader.import_cookies()
     #Transition vers l'écran de soumission CSV du module de reconnaissance numérique
        uploader.go_to_page('https://www.kaggle.com/c/digit-recognizer/submit')
        time.sleep(30) #Ça n'a pas marché sans dormir
     #téléchargement de fichiers
        uploader.input_value(
            '/html/body/main/div[1]/div/div[5]/div[2]/div/div[3]/div[2]/div[2]/div[1]/div[2]/div[1]/div/input',
            file_path,
            wait=False
        )
     #Entrez un commentaire
        uploader.input_value(
            '/html/body/main/div[1]/div/div[5]/div[2]/div/div[3]/div[2]/div[2]/div[2]/div[2]/div/div/div/div[2]/div/div/textarea',
            'test'
        )
        uploader.wait_element(
            '/html/body/main/div[1]/div/div[5]/div[2]/div/div[3]/div[2]/div[2]/div[1]/div[2]/div[1]/ul/li/div/span[1]')
        uploader.click('/html/body/main/div[1]/div/div[5]/div[2]/div/div[3]/div[2]/div[2]/div[3]/div[2]/div/a')
        uploader.wait_value(
            '/html/body/main/div[1]/div/div[5]/div[2]/div/div[2]/div[2]/div/div[3]/div[1]/div[1]/span',
            'Complete'
        )

Classe d'exécution de tâche

homeworker.py


import csv
import datetime
import json
import os
import time


import retrying


from mnist_auto.models.operator import BrowserOperator
from mnist_auto.models.ai import MnistModel


DEFAULT_DAILY_SCORES_DIR = 'daily_scores'
DEFAULT_CSVS_DIR = 'results'
DEFAULT_UPLOADED_SCORE_FILE_NAME = 'uploaded_score.csv'
DEFAULT_KAGGLE_DAILY_LIMIT = 5
COLUMN_DATETIME = 'DATETIME'
COLUMN_SCORE = 'SCORE'
GOOGLE_MAILADDRESS = '[email protected]'
GOOGLE_PASSWORD = 'password'



class BaseHomeworker(object):
    """ Base model of homeworker """

    def __init__(self, daily_score_dir_name, csvs_dir_name):
        self.daily_score_dir_path = self.get_dir_path(daily_score_dir_name)
        self.csvs_dir_path = self.get_dir_path(csvs_dir_name)

    def get_dir_path(self, dir_name):
        """ Function to get directory path
            if direcotry doen't exist, The direcotry will be made

        Params:
            dir_name(str): The directory name
        Returns:
            str: The directory path
        """
        base_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
        dir_path = os.path.join(base_dir, dir_name)
        if not os.path.exists(dir_path):
            os.mkdir(dir_path)
        return dir_path


class Homeworker(BaseHomeworker):
    """ The homeworker model """

    def __init__(self):
        super().__init__(daily_score_dir_name=DEFAULT_DAILY_SCORES_DIR, csvs_dir_name=DEFAULT_CSVS_DIR)
        self.uploaded_scores = []
        self.config = self.get_confing()
        self.mnist_model = MnistModel()

    def get_confing(self, config_file_name='config.json'):
        """ Function to get configuration with json format

        Params:
            config_file_name(str): The name of config file
        Return:
            dict: The dict including config
        """
        base_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
        config_file_path = os.path.join(base_dir, config_file_name)
        json_file = open(config_file_path, 'r')
        return json.load(json_file)

    def write_daily_to_file(self, date_ymd, date_ymdhm, score):
        """ Function to write daily data to file

        Params:
            date_ymd(str): The formatted date (YYYYmmdd)
            date_ymdhm(str): The formatted date (YYYYmmddHHMM)
            score(int): The score
        """
        date_ymd = date_ymd + '.csv'
        file_path = os.path.join(self.daily_score_dir_path, date_ymd)
        with open(file_path, 'a', newline='') as csv_file:
            fieldnames = [COLUMN_DATETIME, COLUMN_SCORE]
            writer = csv.DictWriter(csv_file, fieldnames=fieldnames)
            writer.writerow({
                COLUMN_DATETIME: date_ymdhm,
                COLUMN_SCORE: score
            })


    def upload_csv_files(self, date_ymd, num=DEFAULT_KAGGLE_DAILY_LIMIT):
        """ Function to upload designated number csv files

        Params:
            data_ymd(str): The formatted data
            num(int): The number of file that will be uploaded
        """
        targets_uploaded = self.get_tops(date_ymd, num)
        for target in targets_uploaded:
            file_path = os.path.join(self.daily_score_dir_path, target[COLUMN_DATETIME]) + '.csv'
            try:
                self.upload_csv_to_kaggle(file_path)
            except retrying.RetryError:
                continue

    def get_tops(self, date_ymd, num):
        """ Function to get data that have some high score from daily data

        Params:

            num(int): The number of data that will be gotten

        Return:
            list: The list that includes some highest data
        """
        file_name = date_ymd + '.csv'
        file_path = os.path.join(self.daily_score_dir_path, file_name)
        scores = []
        with open(file_path, 'r') as csv_file:
            reader = csv.reader(csv_file)
            for row in reader:
                scores.append({
                    COLUMN_DATETIME: row[0],
                    COLUMN_SCORE: row[1]
                })
        sorted_list = sorted(scores, key=lambda x: x[COLUMN_SCORE], reverse=True)
        if len(sorted_list) < num:
            num = len(sorted_list)
        return sorted_list[:num]

    @retrying.retry(stop_max_attempt_number=3)
    def upload_csv_to_kaggle(self, file_path):
        """ Function to upload csv file to kaggle

        Params:
            file_path(str): The path of csv file uploaded
        """
        uploader = BrowserOperator()
        uploader.go_to_page(
            'https://www.kaggle.com/c/digit-recognizer'
        )
        uploader.click(
            '/html/body/main/div[1]/div/div[1]/div[2]/div[2]/div[1]/a/div/button'
        )
        uploader.click(
            '/html/body/main/div/div[1]/div/form/div[2]/div/div[1]/a/li/span'
        )
        uploader.input_value(
            '/html/body/div[1]/div[1]/div[2]/div/div[2]/div/div/div[2]/div/div[1]/div/form/span/section/div/div/div[1]/div/div[1]/div/div[1]/input',
            GOOGLE_MAILADDRESS
        )
        uploader.click(
            '/html/body/div[1]/div[1]/div[2]/div/div[2]/div/div/div[2]/div/div[2]/div/div[1]/div'
        )
        uploader.input_value(
            '/html/body/div[1]/div[1]/div[2]/div/div[2]/div/div/div[2]/div/div[1]/div/form/span/section/div/div/div[1]/div[1]/div/div/div/div/div[1]/div/div[1]/input',
            GOOGLE_PASSWORD
        )
        uploader.click(
            '/html/body/div[1]/div[1]/div[2]/div/div[2]/div/div/div[2]/div/div[2]/div/div[1]/div/span/span'
        )
        time.sleep(10)
        uploader.import_cookies()
        uploader.go_to_page('https://www.kaggle.com/c/digit-recognizer/submit')
        time.sleep(30)
        uploader.input_value(
            '/html/body/main/div[1]/div/div[5]/div[2]/div/div[3]/div[2]/div[2]/div[1]/div[2]/div[1]/div/input',
            file_path,
            wait=False
        )
        uploader.input_value(
            '/html/body/main/div[1]/div/div[5]/div[2]/div/div[3]/div[2]/div[2]/div[2]/div[2]/div/div/div/div[2]/div/div/textarea',
            'test'
        )
        uploader.wait_element(
            '/html/body/main/div[1]/div/div[5]/div[2]/div/div[3]/div[2]/div[2]/div[1]/div[2]/div[1]/ul/li/div/span[1]')
        uploader.click('/html/body/main/div[1]/div/div[5]/div[2]/div/div[3]/div[2]/div[2]/div[3]/div[2]/div/a')
        uploader.wait_value(
            '/html/body/main/div[1]/div/div[5]/div[2]/div/div[2]/div[2]/div/div[3]/div[1]/div[1]/span',
            'Complete'
        )
        
    def work(self):
        """ Function to run a series of tasks
                1.  learning and prediction with parameter (It's written on json)
                    one prediction results is outputed as one csv
                2.  Writing learning's score (acc) to another csv.
                3.  Once a day, uploading result csv files to kaggle in high score order
         """
        last_upload_time = datetime.datetime.now()
        for config in self.config['CONFIG']:
            now = datetime.datetime.now()
            now_format_ymdhm = '{0:%Y%m%d%H%M}'.format(now)
            now_format_ymd = '{0:%Y%m%d}'.format(now)
            if (now - last_upload_time).days > 0:
                last_upload_time = now
                self.upload_csv_files()
            csv_file_name = now_format_ymdhm + '.csv'
            csv_file_path = os.path.join(self.csvs_dir_path, csv_file_name)
            score = self.mnist_model.learning_and_predict(csv_file_path=csv_file_path, config=config)
            self.write_daily_to_file(date_ymd=now_format_ymd, date_ymdhm=now_format_ymdhm, score=score)

La méthode de travail est la partie principale.

Annonce des résultats

J'ai pu passer la tâche en dormant presque! Le nombre de téléchargements par chaque stagiaire est affiché, mais seulement j'étais un ordre de grandeur w

image.png

Laissez Python faire les choses ennuyeuses pour vous aussi! !! Puis!

Recommended Posts

(◎◎) {Laissons Python faire les choses ennuyeuses) ......... (Hé? Laissons Python faire les devoirs} (゜) (゜)
"Laissez Python faire les choses ennuyeuses" Exercice ~ Command Line Mailer ~
MoneyForward Cloud automatise l'horodatage [Laissez Python faire le problème]
Recevez le formulaire en Python et faites diverses choses
[Version 2020] Laissez Python faire tous les calculs de taxes et de recettes
Faisons du scraping d'images avec Python
[Blender x Python] Maîtrisons le matériel !!
Laissez Heroku faire le traitement en arrière-plan avec Python
Lisons le fichier RINEX avec Python ①
Résumons le standard de codage Python PEP8 (1)
[Python] Résumez les éléments rudimentaires du multithreading
Résumons le standard de codage Python PEP8 (2)
Faisons la manipulation des données MySQL avec Python
Introduction à Python Préparons l'environnement de développement
Analysons le journal de validation git en Python!
Quand les fonctions python affectent-elles les arguments de l'appelant?
[Python] Exécutons le module régulièrement en utilisant schedule
Web scraping avec Python (prévisions météo)
Web scraping avec Python (cours de l'action)