Ein Buch auf dem Cover eines Roboters wie diesem C-3PO im Gras
Es ist berühmt als ein gutes Buch von Python, und viele Leute haben es vielleicht gelesen.
Also, wer hat dieses Buch gelesen und Python die wirklich langweiligen Dinge machen lassen? Ist es nicht ziemlich klein? Ich denke, es gibt viele Menschen, die mit dem Lesen zufrieden sind. Ich war einer von ihnen. Ich habe es vor ungefähr einem Jahr nur einmal gelesen. .. .. war
In letzter Zeit ist KI ein Buzz geworden. Es scheint, dass verschiedene Unternehmen damit beginnen, KI einzuführen. Das Unternehmen, für das ich arbeite, ist keine Ausnahme, und ich habe begonnen, KI-Training einzuführen.
Während des Trainings hatte ich die Aufgabe, selbst ein Modell für maschinelles Lernen zu erstellen und handgeschriebene Zeichen vorherzusagen.
Definiert ein Modell für tiefes Lernen. Wie viele Ebenen des tiefen Lernens sollten hier verwendet werden, und wie viele Knoten sollten in jeder Ebene verwendet werden? Wir werden die Gesamtkonfiguration und Feinabstimmung des Modells vornehmen.
Trainieren Sie das Modell, indem Sie Daten (Trainingsdaten) übergeben, in denen das richtige Etikett und das Bild handgeschriebener Zeichen gepaart sind. Hier können Sie das vorläufige Vorhersageergebnis messen, indem Sie einen Teil der Trainingsdaten als Verifizierungsdaten verwenden (siehe 3. Vorhersage). Wir werden das Modell mit dem höchsten vorläufigen Vorhersageergebnis für die nachfolgende Arbeit verwenden.
Vorhersage handgeschriebener Zeichen durch Übergabe von Daten (Verifizierungsdaten) nur für Bilder handgeschriebener Zeichen. Die Prognose wird als CSV-Datei ausgegeben.
Laden Sie die Vorhersage-CSV-Datei über einen Browser auf den vom Schulungsunternehmen erstellten Webserver hoch.
Die Genauigkeit des Vorhersageergebnisses wird auf dem Webserver angezeigt.
Die Herausforderung bestand darin, die Genauigkeit der bestandenen Punktzahl durch Wiederholen der obigen Schritte 1 bis 5 zu ermitteln.
Nachdem ich es mehrmals wiederholt hatte, kam ich zu dem Schluss, dass dies eine Routinearbeit war. Sobald der Umriss des Modells festgelegt ist, müssen Sie nur noch die Parameter des Modells einstellen und das Lernen wiederholen -> Vorhersage → Übermittlung. Außerdem ist die Wartezeit sehr lang! !! Ich habe mich gefragt, ob dies automatisiert werden kann.
Let's automation with python
Lassen wir Python die langweiligen Dinge tun.
Dies erfolgt in einer interaktiven Python-Ausführungsumgebung namens Jupyter Notebook. Ich dachte, dass Automatisierung realisiert werden könnte, indem der in Jupyter-Notizbuch geschriebene Code in eine Python-Klasse / -Funktion umgewandelt und die für die Optimierung verwendeten Parameter als Argument übergeben werden.
So konvertieren Sie Jupyter-Notebook-Code in eine Python-Datei https://qiita.com/abts/items/25bb611b6d83e646abdd
Laden Sie die CSV-Datei, die durch Vorhersage ausgegeben wurde, über Google Chrome auf die Upload-Site hoch. Es scheint, dass der Webbrowser mithilfe einer Python-Bibliothek namens Selenium automatisiert werden kann.
Über Selen https://qiita.com/Chanmoro/items/9a3c86bb465c1cce738a
Es gab ein Limit, dass Sie nur bis zu 5 vorhergesagte CSV-Dateien pro Tag hochladen können. Ohne dies wäre es einfacher gewesen, den obigen Prozess einfach zu durchlaufen. .. .. Es scheint, dass wir hier etwas entwickeln müssen.
Dies ist ein Schleifenprozess.
Es wird einmal am Tag wiederholt, nur fünfmal nach Mitternacht. Fünfmal ist die maximale Anzahl von Einreichungen pro Tag.
Wie erwartet kann die Upload-Site des Schulungsunternehmens nicht veröffentlicht werden. Daher verwenden wir dieses Mal stattdessen den Ziffernerkenner von kaggle. Der Grundfluss ändert sich nicht. Außerdem hat kaggle eine API zum Hochladen, aber lassen Sie sich diesmal nicht täuschen (-_-) Ich hoffe, Sie können dies als Reproduktion sehen.
Lassen Sie uns kurz den tatsächlich verwendeten Code erklären.
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]
Das Modell dieses maschinellen Lernens wurde unter Bezugnahme auf das Folgende (rundes Pakuri) erstellt. https://www.kaggle.com/yassineghouzam/introduction-to-cnn-keras-0-997-top-6
Verwenden Sie die Methode learning_and_predict, um alle Modelle zu erstellen / zu lernen / vorherzusagen. config ist eine Liste von Parametern.
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)
Dieses Mal werden die Parameter des Bilddatengenerators optimiert.
{
"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
}
]
}
Dies ist eine Klasse zum Hochladen von Predictive CSV auf eine Website. Es wird hauptsächlich in Selen eingesetzt.
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
Verwenden Sie jede Methode wie folgt.
Sie können die vorhergesagte CSV-Datei mit kaggle mit dem folgenden Code hochladen.
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()
#Übergang zur Kaggle-Seite
uploader.go_to_page(
'https://www.kaggle.com/c/digit-recognizer'
)
#Klicken Sie auf die Schaltfläche Anmelden
uploader.click(
'/html/body/main/div[1]/div/div[1]/div[2]/div[2]/div[1]/a/div/button'
)
#Klicken Sie auf Mit Google anmelden
uploader.click(
'/html/body/main/div/div[1]/div/form/div[2]/div/div[1]/a/li/span'
)
#Geben sie ihre E-Mailadresse ein
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'
)
#Passwort eingeben
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) #Ohne Schlaf ging es nicht
#Cookies importieren
uploader.import_cookies()
#Übergang zum CSV-Übermittlungsbildschirm des Ziffernerkenners
uploader.go_to_page('https://www.kaggle.com/c/digit-recognizer/submit')
time.sleep(30) #Ohne Schlaf ging es nicht
#Datei-Upload
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
)
#Geben Sie einen Kommentar ein
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'
)
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)
Die Arbeitsmethode ist der Hauptteil.
Ich konnte die Aufgabe bestehen, indem ich fast schlief! Die Anzahl der Uploads von jedem Auszubildenden wird angezeigt, aber nur ich war eine Größenordnung w
Lassen Sie Python auch die langweiligen Dinge für Sie erledigen! !! Dann!
Recommended Posts