Intelligence Artificielle : le clavier android

Salut à tous …

Depuis que je joue un peu avec les intelligences artificielles, je m’amuse à regarder les divers éléments du quotidien qui utilisent ou pourraient utiliser des intelligences artificielles … et le clavier android en est un … je ne suis pas sûr de mon approche, mais pour le moment, ça semble fonctionnelle (malgrès un corpus de données très court).

La version courte est disponible sur youtube la version longue/texte est ici.

L’idée du clavier android, est de deviner le mot suivant dans la phrase courante (à noter que pour le moment l’AI de google ne garde pas le contexte au-delà du . de la phrase).

pasted-image-0

Mes différentes approches

  1. tentative de deviner la lettre qui suit la lettre courante clavier_lettre
  2. tentative de deviner directement le mot qui suit le mot courantclavier_mot

1er Cas : Prédiction de la lettre suivante

Le code simplifié préparation des données :

#preparation des données
    maxlen = 40 (longueur max pour l'entrainement).
    total_text = "... vos phrases de test"
    chars = set(total_text)
    char_indices = dict((c, i) for i, c in enumerate(chars))
    indices_char = dict((i, c) for i, c in enumerate(chars))
    step = 1
    sentences = []
    next_chars = []
    for i in range(0, len(total_text) - maxlen, step):
        sentences.append(total_text[i: i + maxlen])
        next_chars.append(total_text[i + maxlen])
    print('nb sequences:', len(sentences))
    print('nb ci:', len(char_indices))
    print('nb ic:', len(indices_char))

    X = np.zeros((len(sentences), maxlen, len(chars)), dtype=np.bool)
    y = np.zeros((len(sentences), len(chars)), dtype=np.bool)
    for i, sentence in enumerate(sentences):
        for t, char in enumerate(sentence):
            X[i, t, char_indices[char]] = 1
        y[i, char_indices[next_chars[i]]] = 1

On se contente de dire à l’AI que la « phrase courante = lettre suivante » (fait via le one hot encoding (cf ma vidéo d’intro sur les AI) mis en évidence dans le code ci-dessus).

Le code de l’IA en elle même :

(basé sur : http://arxiv.org/abs/1312.4569)

#AI
    model = Sequential()
    model.add(LSTM(len(chars), input_length=maxlen, input_dim=len(char_indices), return_sequences=True))
    model.add(Dropout(0.20))
    model.add(LSTM(512, return_sequences=True))
    model.add(Dropout(0.20))
    model.add(LSTM(512, return_sequences=True))
    model.add(Dropout(0.20))
    model.add(LSTM(256, return_sequences=False))
    model.add(Dropout(0.20))
    model.add(Dense(len(chars)))
    model.add(Activation('softmax'))
    model.compile(loss='categorical_crossentropy', optimizer='rmsprop')
    model.fit(X,y,nb_epoch=50)

Pour générer le texte, on peut passer par le code suivant :

    seed_text = "debut de phrase voulu"
    generated = '' + seed_text
    print('------'*5+'\ndemande: \n'+'"' + seed_text +'"')
    while len(seed_text)<maxlen:
        seed_text=' '+seed_text
    print('------'*5+'\n generation...\n'+ '------'*5)
    for iteration in range(150):
        x = np.zeros((1, maxlen, len(chars)))
        for t, char in enumerate(seed_text):
            x[0, t, char_indices[char]] = 1.
        preds = model.predict(x, verbose=0)[0]
        next_index = np.argmax(preds)
        next_char = indices_char[next_index]
        generated += next_char
        seed_text = seed_text[1:] + next_char
    print('\n\nphrase générée: ' + generated)

Résultats : Avantages/Inconvénients

  • — Apprentissage très lent (6 heures).
  • ++ Execution rapide après récupération du model
  • ++ L’AI peut réagir sur des mots inconnus (« ressemblance mathématique » du mot).
  • ++ choses amusante, après apprentissage d’un corpus de 44000 mots français, l’AI ne m’a sortie que des mots français … alors qu’elle n’avait appris que des lettres (ponctuations incluses) … elle aurait pu me sortir n’importe quoi, mais non 🙂
  • — Contexte de souvenir très court (dans mon cas, après 20 caractères, mon AI commençait à boucler … cela dit si vous utilisez uniquement les suggestions de google, vous aurez aussi des boucles :)).

2nd Cas : Prédiction du mot suivant

Le code de préparation des données est quasiment similaire.

    total_text = "échantillon de test".split()
    chars = set(total_text)
    char_indices = dict((c, i) for i, c in enumerate(chars))
    indices_char = dict((i, c) for i, c in enumerate(chars))
    maxlen = 5 (taille du contexte : ici beaucoup plus courte)
    step = 1
    sentences = []
    next_chars = []
    for i in range(0, len(total_text) - maxlen, step):
        sentences.append(total_text[i: i + maxlen])
        next_chars.append(total_text[i + maxlen])
    print('nb sequences:', len(sentences))
    print('nb ci:', len(char_indices))
    print('nb ic:', len(indices_char))

    X = np.zeros((len(sentences), maxlen, len(chars)), dtype=np.bool)
    y = np.zeros((len(sentences), len(chars)), dtype=np.bool)
    for i, sentence in enumerate(sentences):
        for t, char in enumerate(sentence):
            X[i, t, char_indices[char]] = 1
        y[i, char_indices[next_chars[i]]] = 1

L’apprentissage est le même qu’au dessus :). La magie des algo d’apprentissage, aucun dev à faire.

La génération de texte est la suivante :

    seed_text = "début de texte recherché".split()
    while len(seed_text)<4:
        seed_text.insert(0,'!')
    generated = '' + text
    print('------'*5+'\ndemande: \n'+'"' + text +'"')
    print('------'*5+'\n generation...\n'+ '------'*5)
    for iteration in range(22):
        x = np.zeros((1, maxlen, len(chars)))
        for t, char in enumerate(seed_text):
            x[0, t, char_indices[char]] = 1.
        preds = model.predict(x, verbose=0)[0]
        next_index = np.argmax(preds)
        next_char = indices_char[next_index]
        generated += ' '+next_char
        seed_text.append(next_char)
        seed_text = seed_text[1:]
    print('\n\nphrase générée: ' + generated)

Résultats : Avantages/Inconvénients

  • ++ Apprentissage beaucoup plus rapide : 30 min
  • ++ Contexte de souvenir plus large
  • — L’AI est incapable de réagir de façon précise sur des mots inconnus.

Conclusion(s)

Il existe bien entendu des milliers d’approche sur le sujet (il suffit de lire les thèses et autres docs sur le sujet).

Mais j’aime bien l’approche très simpliste présenté ici, le résultat est même surprenant pour la partie prédictions de lettres avec une prédictions de mot français uniquement, la où elle aurait pu sortir des mots composé de ponctuations seulement. Le seul problème étant le contexte plutôt court, en utilisant un contexte plus large il me faut plusieurs jours d’apprentissage si je veux utiliser des contextes plus long.

Concernant l’AI par mot, malgrès sa plus grosse réussite que l’autre AI, son incapacité à réagir sur des mots inconnus est problématique.