[PYTHON] Lassen Sie die Maschine die Regeln von FizzBuzz "lernen"

** * Ergänzung ** Es gab bereits einen Beitrag mit ähnlichem Inhalt.

Guten Abend. Dies ist Rizento.

Die meisten von Ihnen, die diesen Artikel lesen, kennen FizzBuzz. Wenn Sie ein Programmierer sind, können Sie gemäß den Regeln von FizzBuzz eine Ausgabe von 1 bis 100 haben. Dieses Mal werde ich versuchen, dieses FizzBuzz zu machen "Lass es AI tun, ohne Code zu schreiben". Das erstellte Programm wird auf GitHub veröffentlicht.

Inhaltsverzeichnis

  1. [Was ist FizzBuzz](Was ist #FizzBuzz)
  2. [Spielelemente organisieren](# Spielelemente organisieren)
  3. [Erstellen einer Spielumgebung](#Erstellen einer Spielumgebung)
  4. [Erstellen eines Lernmodells](#Erstellen eines Lernmodells)
  5. [Lerngedächtnis aufbauen](# Lerngedächtnis aufbauen)
  6. [Build Learning Agent](#Build Learning Agent)
  7. [Versuche zu lernen](# Lass uns lernen)
  8. Ergebnis

?

Was ist FizzBuzz?

Wenn Sie wissen, was es ist, überspringen Sie es bitte.

Schauen Sie sich [Wikipedia] an (https://ja.wikipedia.org/wiki/Fizz_Buzz).

Fizz Buzz (auch bekannt als Fizz Buzz, Bizz Buzz oder Buzz) ist ein Wortspiel, das während Langstreckenfahrten und Trinkpartys im englischsprachigen Raum stattfindet.

Einfach ausgedrückt, wenn Sie die Zahlen der Reihe nach auflisten, ** Fizz ** anstelle von Zahlen bei Vielfachen von 3, ** Buzz ** bei Vielfachen von 5, ** FizzBuzz bei beiden Es ist ein Spiel namens **. Es ist Nabeats der Welt.

Organisieren Sie die Elemente des Spiels

Es ist 2020 und es ist für Menschen veraltet, FizzBuzz nicht mehr zu spielen. Lassen Sie uns nur die Spielregeln von Menschen vorbereiten und die Maschine den Rest spielen lassen.

Die diesmal verwendete Methode ist ** erweitertes Lernen **. Es ist eine Technik, die häufig für KI in Spielen verwendet wird, und wird auch für KI in Go und Shogi verwendet.

Ich werde hier nicht über das Lernen der Verstärkung schreiben. Wenn Sie interessiert sind, überzeugen Sie sich selbst.

Wenn Menschen FizzBuzz spielen, können sie tatsächlich eine Antwort geben, wenn sie nur die aktuelle Nummer kennen, aber da es keinen KI-Geschmack hat, ist diesmal ** Antwort für die letzten 15 Runden ** jetzt Gib AI als ** Status ** von.

Aufbau einer Spielumgebung

Erstellen Sie zunächst die Spielumgebung von FizzBuzz. Insbesondere sind die folgenden Funktionen implementiert.

Die ** Punktzahl ** hier gibt an, wie gut jede Antwort (Nummer, FIzz, Buzz, FizzBuzz) auf die aktuelle Situation für AI ist. Die KI wird mit dem Ziel wachsen, diese Punktzahl weiterhin zu erzielen.

FizzBuzz.py


from random import randint
from numpy import array

class FizzBuzz:
    def __init__(self, start, end):
        self.start = start #Anfang
        self.end   = end   #das Ende

    def reset(self): #Initialisieren
        self.turn = self.start #Aktuelle Nummern
        self.state = []        #Aktuellen Zustand

        #Anfangsstatus einstellen(Letzte 15 Runden)
        for i in range(self.turn - 15, self.turn):
            if i % 15 == 0:
                self.state.append(3)
            elif i % 3 == 0:
                self.state.append(1)
            elif i % 5 == 0:
                self.state.append(2)
            else:
                self.state.append(0)

    #Ob du genug gelernt hast
    def is_learned(self):
        return self.turn == self.end

    #Übergang drehen
    def step(self, action, verbose=False):
        if verbose:
            print(self.turn, [self.turn, 'Fizz', 'Buzz', 'FizzBuzz'][action])

        reward   = 0     #Ergebnis
        terminal = False #Spielende Urteil

        self.state = self.state[1:] + [action]

        if action == 1:   # Fizz
            if self.turn % 3 == 0 and self.turn % 5 != 0:
                reward   = 1
                terminal = False
            else:
                reward   = -1
                terminal = True
        elif action == 2: # Buzz
            if self.turn % 5 == 0 and self.turn % 3 != 0:
                reward   = 1
                terminal = False
            else:
                reward   = -1
                terminal = True
        elif action == 3: # FizzBuzz
            if self.turn % 15 == 0:
                reward   = 1
                terminal = False
            else:
                reward   = -1
                terminal = True
        else:             # Number
            if self.turn % 3 != 0 and self.turn % 5 != 0:
                reward   = 1
                terminal = False
            else:
                reward   = -1
                terminal = True

        if self.turn == self.end:
            terminal = True

        self.turn += 1

        return array(self.state), reward, terminal

    def random_step(self): #Zur Initialisierung
        return array(self.state), 0, False

Wiederholen Sie nach dem Initialisieren mit reset () das Lernen, während Sie mit step () übergehen. Außerdem habe ich is_learned () geschrieben, um das Ende zu beurteilen, damit das Lernen automatisch aufgerundet werden kann, wenn das Spiel die letzte Zahl erreicht.

Aufbau eines Lernmodells

Erstellen Sie als Nächstes ein ** Modell **, das Sie tatsächlich zum Lernen verwenden. Dieses Mal werden wir ein neuronales Netzwerk mit einer einfacheren Struktur in der mittleren Schicht verwenden.

model.py


from keras.models import Sequential
from keras.layers import Dense, Reshape
from keras.optimizers import Adam
import numpy as np

class Model:
    def __init__(self):
        learning_rate = 0.01 #Lernrate
        state_size    = 15   #Eingabegröße(Aktuellen Zustand)
        action_size   = 4    #Ausgabegröße(0, 1, 2, 3)
        hidden_size   = 16   #Die Größe der ausgeblendeten Ebene

        self.model = Sequential()
        self.model.add(Dense(hidden_size, activation='relu', input_dim=state_size))
        self.model.add(Dense(action_size, activation='softmax'))
        self.optimizer = Adam(lr=learning_rate)
        self.model.compile(loss='mse', optimizer=self.optimizer)
        self.model.summary()

    #Funktionen, um tatsächlich zu lernen
    def replay(self, memory, batch_size, gamma, target_model):
        inputs     = np.zeros((batch_size, 15))
        outputs    = np.zeros((batch_size, 4))
        mini_batch = memory.sample(batch_size)

        for i, (state, action, reward, next_state) in enumerate(mini_batch):
            inputs[i:i + 1] = state
            target          = reward

            if not (next_state == np.zeros(state.shape)).all():
                q = self.model.predict(next_state.reshape(1, 15))[0].argmax()
                next_action = np.argmax(q) #Wählen Sie als nächste Aktion die Aktion mit dem höchsten Q-Wert aus
                target = reward + gamma * target_model.model.predict(
                    next_state.reshape(1, 15)
                )[0][next_action] #Tatsächliche Belohnung

            #Korrigieren Sie den aktuell erwarteten Wert und lassen Sie ihn lernen
            outputs[i] = self.model.predict(state.reshape(1, 15))
            outputs[i][action.argmax()] = target

        self.model.fit(inputs, outputs, epochs=1, verbose=0)

Verwenden Sie replay (), wenn Sie tatsächlich lernen. Wenn Sie jede Runde trainieren, wird das Modell von der Zeitreihe der Daten beeinflusst, sodass eine bestimmte Datenmenge im ** Speicher ** gespeichert wird, der später implementiert wird, und für das Training zufällig daraus extrahiert wird. Ich werde.

Lerngedächtnis aufbauen

Implementieren Sie einen Speicher zum Speichern der zum Lernen verwendeten Daten.

memory.py


from collections import deque
import numpy as np

class Memory:
    def __init__(self):
        self.buffer = deque()

    #Speichert die aktuelle Situation, wie es funktioniert hat, was als Ergebnis passiert ist und die Belohnung für diese Aktion
    def add(self, exp):
        self.buffer.append(exp)

    #Ruft zufällig gespeicherte Daten ab
    def sample(self, batch_size):
        indice = np.random.choice(np.arange(len(self.buffer)), size=batch_size, replace=False)
        return [self.buffer[i] for i in indice]

Erstellen Sie einen Lernagenten

Eine Person (?), Die während des Lernens tatsächlich über eine Aktion entscheidet und anhand des Ergebnisses lernt, wird als ** Agent ** bezeichnet.

agent.py


import numpy as np
from keras.utils.np_utils import to_categorical

class Agent:
    #Wähle eine Aktion
    def get_action(self, state, epoch, main_model):
        epsilon = 0.001 + 0.9 / (1.0 + epoch)

        if epsilon < np.random.uniform(0, 1):
            action = main_model.model.predict(state.reshape(1, 15))[0].argmax()
        else: #Zufälliges Verhalten mit einer bestimmten Wahrscheinlichkeit
            action = np.random.choice([0, 1, 2, 3])

        return to_categorical(action, 4)

Wählen Sie die Aktion mit get_action () aus. Grundsätzlich wird das vom Modell erwartete Verhalten ausgewählt, aber durch Ausführen zufälliger Bewegungen mit einer bestimmten Wahrscheinlichkeit ist es möglich, ein sogenanntes ** Abenteuer ** zu machen und einen neuen guten Zug zu entdecken.

Lass uns tatsächlich lernen

Lassen Sie uns das Lernen mit den oben implementierten Personen drehen.

train.py


from fizzbuzz import FizzBuzz
from model import Model
from memory import Memory
from agent import Agent

def evaluate(env):
    env.reset()
    state, _, finished = env.random_step()
    while not finished:
        action = agent.get_action(state, N_EPOCHS, main_model)
        next_state, _, finished = env.step(action.argmax(), verbose=True)
        state = next_state

if __name__ == '__main__':
    N_EPOCHS = 5000 #Maximale Anzahl von Schulungen
    S_BATCH  = 4    #Chargengröße
    GAMMA    = 0.99 #Belohnungsreduktionsrate im Laufe der Zeit

    env = FizzBuzz(1, 1000) #Lernumgebung

    main_model   = Model()
    target_model = Model()

    memory = Memory() #Erinnerung
    agent  = Agent()  #Agent

    learned_flag = False #Ob das Lernen abgeschlossen ist

    for epoch in range(N_EPOCHS):
        if learned_flag:
            break

        print('Epoch: {}'.format(epoch + 1))

        #Einstellung des Anfangszustands
        env.reset()
        state, reward, finished = env.random_step() 
        target_model.model.set_weights(main_model.model.get_weights())

        while not finished:
            action = agent.get_action(state, epoch, main_model)
            learned_flag = env.is_learned()
            next_state, reward, finished = env.step(action.argmax())

            memory.add((state, action, reward, next_state))

            state = next_state

            if len(memory.buffer) > S_BATCH:
                main_model.replay(memory, S_BATCH, GAMMA, target_model)

            target_model.model.set_weights(main_model.model.get_weights())

    env = FizzBuzz(1, 100)
    evaluate(env)

Wir haben auch evaluieren () implementiert, um am Ende des Lernens zu evaluieren. Sie können dies überprüfen, während Sie FizzBuzz tatsächlich ausgeben.

Ergebnis

Es ist ein Lernergebnis.

Epoch: 70
Epoch: 71
Epoch: 72
1 1, 2 2, 3 Fizz, 4 4, 5 Buzz, 6 Fizz, 7 7, 8 8, 9 Fizz, 10 Buzz, 11 11, 12 Fizz, 13 13, 14 14,
15 FizzBuzz, 16 16, 17 17, 18 Fizz, 19 19, 20 Buzz, 21 Fizz, 22 22, 23 23, 24 Fizz, 25 Buzz, 26 26,
27 Fizz, 28 28, 29 29, 30 FizzBuzz, 31 31, 32 32, 33 Fizz, 34 34, 35 Buzz, 36 Fizz, 37 37, 38 38,
39 Fizz, 40 Buzz, 41 41, 42 Fizz, 43 43, 44 44, 45 FizzBuzz, 46 46, 47 47, 48 Fizz, 49 49, 50 Buzz,
51 Fizz, 52 52, 53 53, 54 Fizz, 55 Buzz, 56 56, 57 Fizz, 58 58, 59 59, 60 FizzBuzz, 61 61, 62 62,
63 Fizz, 64 64, 65 Buzz, 66 Fizz, 67 67, 68 68, 69 Fizz, 70 Buzz, 71 71, 72 Fizz, 73 73, 74 74,
75 FizzBuzz, 76 76, 77 77, 78 Fizz, 79 79, 80 Buzz, 81 Fizz, 82 82, 83 83, 84 Fizz, 85 Buzz, 86 86,
87 Fizz, 88 88, 89 89, 90 FizzBuzz, 91 91, 92 92, 93 Fizz, 94 94, 95 Buzz, 96 Fizz, 97 FizzBuzz,
98 98, 99 Fizz, 100 Buzz

Nach 72 Lernrunden konnte ich 1 bis 100 erreichen.

Versuchen wir die Ergebnisse von 4000.

4000 Buzz, 4001 4001, 4002 Fizz, 4003 4003, 4004 4004, 4005 FizzBuzz, 4006 4006, 4007 4007, 4008 Fizz,
4009 4009, 4010 Buzz, 4011 Fizz, 4012 4012, 4013 4013, 4014 Fizz, 4015 Buzz, 4016 4016, 4017 Fizz,
4018 4018, 4019 4019, 4020 FizzBuzz, 4021 4021, 4022 4022, 4023 Fizz, 4024 4024, 4025 Buzz, 4026 Fizz,
4027 4027, 4028 4028, 4029 Fizz, 4030 Buzz, 4031 4031, 4032 Fizz, 4033 4033, 4034 4034, 4035 FizzBuzz,
4036 4036, 4037 4037, 4038 Fizz, 4039 4039, 4040 Buzz, 4041 Fizz, 4042 4042, 4043 4043, 4044 Fizz,
4045 Buzz, 4046 4046, 4047 Fizz, 4048 4048, 4049 4049, 4050 FizzBuzz, 4051 4051, 4052 4052, 4053 Fizz,
4054 4054, 4055 Buzz, 4056 Fizz, 4057 4057, 4058 4058, 4059 Fizz, 4060 Buzz, 4061 4061, 4062 Fizz,
4063 4063, 4064 4064, 4065 FizzBuzz, 4066 4066, 4067 4067, 4068 Fizz, 4069 4069, 4070 Buzz, 4071 Fizz,
4072 4072, 4073 4073, 4074 Fizz, 4075 Buzz, 4076 4076, 4077 Fizz, 4078 4078, 4079 4079, 4080 FizzBuzz,
4081 4081, 4082 4082, 4083 Fizz, 4084 4084, 4085 Buzz, 4086 Fizz, 4087 4087, 4088 4088, 4089 Fizz,
4090 Buzz, 4091 4091, 4092 Fizz, 4093 4093, 4094 4094, 4095 FizzBuzz, 4096 4096, 4097 4097, 4098 Fizz,
4099 4099, 4100 Buzz, 4101 Fizz, 4102 4102, 4103 4103, 4104 Fizz, 4105 Buzz, 4106 4106, 4107 Fizz,
4108 4108, 4109 4109, 4110 FizzBuzz, 4111 4111, 4112 4112, 4113 Fizz, 4114 4114, 4115 Buzz, 4116 Fizz,
4117 4117, 4118 4118, 4119 Fizz, 4120 Buzz, 4121 4121, 4122 Fizz, 4123 4123, 4124 4124, 4125 FizzBuzz,
4126 4126, 4127 4127, 4128 Fizz, 4129 4129, 4130 Buzz, 4131 Fizz, 4132 4132, 4133 4133, 4134 Fizz,
4135 Buzz, 4136 4136, 4137 Fizz, 4138 4138, 4139 4139, 4140 FizzBuzz, 4141 4141, 4142 4142, 4143 Fizz,
4144 4144, 4145 Buzz, 4146 Fizz, 4147 4147, 4148 4148, 4149 Fizz, 4150 Buzz, 4151 4151, 4152 Fizz,
4153 4153, 4154 4154, 4155 FizzBuzz, 4156 4156, 4157 4157, 4158 Fizz, 4159 4159, 4160 Buzz, 4161 Fizz,
4162 4162, 4163 4163, 4164 Fizz, 4165 Buzz, 4166 4166, 4167 Fizz, 4168 4168, 4169 4169, 4170 FizzBuzz,
4171 4171, 4172 4172, 4173 Fizz, 4174 Fizz

Im 174. 4174 wurde die Ausgabe von ** 4174 ** mit ** Fizz ** verwechselt. Es sollte nur ungefähr 15 Arten von Staaten geben, also frage ich mich, warum ich einen Fehler gemacht habe ...

Übrigens, wenn Sie das Argument verbose = True zu step () in der 43. Zeile von train.py hinzufügen, können Sie sehen, wie es lernt, während Sie die Anzahl der Umdrehungen schrittweise erhöhen. süß.

Wenn Sie möchten, folgen Sie bitte Twitter. Tschüss.

Recommended Posts

Lassen Sie die Maschine die Regeln von FizzBuzz "lernen"
Überprüfung der Grundlagen von Python (FizzBuzz)
Lernen Sie die Grundlagen von Python ① Grundlegende Anfänger
Lernen Sie noch einmal die Grundlagen von Theano
[Linux] Lernen Sie die Grundlagen von Shell-Befehlen
Lernen Sie intuitiv die Umformung von Python np
Bis Sie versuchen, DNN mithilfe von Colab die Wahrheit des Bildes mitteilen zu lassen
Über die Entwicklungsinhalte des maschinellen Lernens (Beispiel)
Lerne Nim mit Python (ab Anfang des Jahres).
Eindrücke vom Udacity Machine Learning Engineer Nano-Abschluss
Lernen Sie das Entwurfsmuster "Chain of Responsibility" in Python
Prognostizieren Sie das Geschlecht von Twitter-Nutzern durch maschinelles Lernen
Zusammenfassung des grundlegenden Ablaufs des maschinellen Lernens mit Python
Der Beginn von cif2cell
Die Bedeutung des Selbst
der Zen von Python
Die Geschichte von sys.path.append ()
Lerne irgendwie maschinelles Lernen
Rache der Typen: Rache der Typen
Versuchen Sie, die Leistung des Modells für maschinelles Lernen / Regression zu bewerten
Umfrage zum Einsatz von maschinellem Lernen in realen Diensten
Vorhersage des Vorhandenseins oder Nichtvorhandenseins von Untreue durch maschinelles Lernen
Versuchen Sie, die Leistung des Modells für maschinelles Lernen / Klassifizierung zu bewerten
[Maschinelles Lernen] Ich habe versucht, die Theorie von Adaboost zusammenzufassen