<jupyter_start><jupyter_text>Abstract Tenter de prédire à quel personnage de GoT correspond une tirade au hasard, voilà l'objet de ce notebook.  Résultat Héals, le volume de donnée est insuffisant pour parvenir à un résultat<jupyter_code># Générique data project
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns

# Pour la manipulation de fichiers
import os
import glob
from pathlib import Path

# Prépa données
from sklearn.model_selection import train_test_split

# Evaluation
from sklearn.metrics import confusion_matrix
from sklearn.metrics import classification_report

# Deep learning
import tensorflow as tf
from tensorflow.keras.layers import RNN,GRUCell,Dropout,GlobalAveragePooling1D,Dense,Embedding
from tensorflow.keras import Sequential

# Txt mining
import re

# MISC
import warnings
warnings.filterwarnings("ignore")
import swifter
import random<jupyter_output><empty_output><jupyter_text>On importe le dataset et on en présente quelques lignes<jupyter_code>df =pd.read_csv('game-of-thrones.csv')
df
df = df.dropna()<jupyter_output><empty_output><jupyter_text>On se propose d'entrainer un algorithme de sorte qu'il soit capable d'idientifier correctement 6 protagonistes phare de l'oeuvre, choisi pour leur durée de vie dans la série (de façon à maixmiser le nombre d'entrée dans la dataframe):- <NAME>- <NAME>- <NAME>- <NAME>- <NAME> Il parait pertinent de vérifier le contenu de la variable "Speaker" afin de vérifier les éventuels biais qu'il nous faudra corriger / éviter:<jupyter_code>df.Speaker.unique()<jupyter_output><empty_output><jupyter_text>Les biais habituels sur ce genre de dataset sont bien présents:- des noms de personnage en majuscule / minuscule- des fautes d'orthographes- différentes appellation d'un même personnage (avec ou sans prénom, nom de jeune fille, avec ou sans surnom,etc...) Ainsi, pour simplifier, on procède aux opérations suivantes:- Ramener toutes les entrées en minuscule- Filtrer avec le plus petit éléments identificateur d'un personnage (par exemple: <NAME> devient Arya)<jupyter_code>df.Speaker = df.Speaker.apply(lambda x : x.lower())
def filtre(x):
    if 'arya' in x:
        return 'arya'
    
    if 'jaime' in x :
        return 'jaime'
    
    if 'jon' in x :
        return 'jon'
    
    if 'daenerys' in x:
        return 'daenerys'
    
    if 'daenarys' in x:
        return 'daenerys'
    
    if 'danaerys' in x:
        return 'daenerys'
    
    if 'deanerys' in x:
        return 'daenerys'
    
    
    if 'tyrion' in x:
        return 'tyrion'
    
    if 'cersei' in x:
        return 'cersei'
    
    if 'cesei' in x:
        return 'cersei'
    
    else:
        return x
df.Speaker = df.Speaker.apply(lambda x : filtre(x))
df.Speaker.unique()<jupyter_output><empty_output><jupyter_text>On produit la dataframe ne contenant que ces personnages<jupyter_code>perso = ['arya','jon','jaime','tyrion','cersei','daenerys']
data = df[df.Speaker.isin(perso)].reset_index().drop(['index'],axis = 1)
data<jupyter_output><empty_output><jupyter_text>On vérifie que les personnages ont un taux d'occurence similaire dans la dataframe<jupyter_code>plt.barh(data.Speaker.value_counts().index,data.Speaker.value_counts().values)
plt.show()<jupyter_output><empty_output><jupyter_text>Il est à craindre que le volume de donnée soit insuffisant A partir de cette étape, on met en oeuvre les opérations qui vont nous permettre d'entrainer un modèle RNN - On associe à chaque personnage un id numérique<jupyter_code>dictus ={u:i for i,u in enumerate(perso)}
data['id']=data.Speaker.apply(lambda x: dictus[x])
data<jupyter_output><empty_output><jupyter_text>- On récupère la liste des mots, à partir de laquelle on produit la liste des mots uniques<jupyter_code>def filtre_mot(texte):
    r = re.compile(r"\W+")
    return r.split(texte)
                   
word = [element for liste in data.Text.values for element in filtre_mot(liste)]
unik_word = sorted(set(word))
len(unik_word)<jupyter_output><empty_output><jupyter_text>- Pour chaque texte de chaque personnage, on associe une liste comprenant chaque mot du texte<jupyter_code>data['phrase']=data.Text.apply(lambda x: filtre_mot(x))
data['longueur']=data.phrase.apply(lambda x : len(x))
data
data.longueur.unique()
plt.barh(data.longueur.value_counts().index,data.longueur.value_counts().values)
plt.ylim([0,50])
plt.show()<jupyter_output><empty_output><jupyter_text>Il nous faut choisir à présent une longueur unique pour nos données d'entrainement. Il faut trouver un compromis entre le nombre minimal de mot requis pour maximiser nos chance de différenciation versus le volume de donnée résiduel sans altération. On postule que 10 élément par liste est un nombre suffisant pour permettre un  bon entrainement et qu'il maximise el nombre de donnée restante.<jupyter_code>taille_seq = 10<jupyter_output><empty_output><jupyter_text>- On transforme chaque liste de mot en séquence d'entier, sur la base des mots uniques précédemment obtenus<jupyter_code>tokenizer_word = tf.keras.preprocessing.text.Tokenizer(num_words=len(unik_word))
tokenizer_word.fit_on_texts(data.phrase)

X = tokenizer_word.texts_to_sequences(data.phrase)<jupyter_output><empty_output><jupyter_text>- On fait en sorte que toutes les listes aient la même longueur<jupyter_code>X = tf.keras.preprocessing.sequence.pad_sequences(X, maxlen=taille_seq, padding='post', truncating='post')
X_train_top,X_test_top,y_train_top,y_test_top = train_test_split(X,data.id,test_size = 0.15,random_state = 1234,shuffle = True)
X_train_top = np.asarray(X_train_top)
X_test_top = np.asarray(X_test_top)
y_train_top = np.asarray(y_train_top)
y_test_top = np.asarray(y_test_top)

print(f'shape of X_train_top : {X_train_top.shape}')
print(f'shape of X_test_top : {X_test_top.shape}')
print(f'shape of y_train_top : {y_train_top.shape}')
print(f'shape of y_test_top : {y_test_top.shape}')
word2idx = tokenizer_word.word_index
idx2word = tokenizer_word.index_word
vocab_word_size = tokenizer_word.num_words
model = tf.keras.Sequential()

model.add(Embedding(vocab_word_size+1,256,input_length=taille_seq))
model.add(RNN(GRUCell(256),return_sequences = False))
model.add(Dropout(0.4))

model.add(Dense(256,'relu'))

model.add(Dropout(0.3))

model.add(Dense(6,'softmax'))

epok = 15

opt = tf.keras.optimizers.Adam(learning_rate=0.007)

model.compile(loss = 'sparse_categorical_crossentropy',optimizer ='adam',metrics =["accuracy"])

training_history = model.fit(X_train_top,y_train_top,validation_data=(X_test_top,y_test_top) ,epochs = epok, batch_size = 128)
train_acc = training_history.history['accuracy']
val_acc = training_history.history['val_accuracy']

plt.xlabel('Epochs')
plt.ylabel('accuracy')

plt.plot(np.arange(1,epok +1,1),training_history.history['accuracy'], label='Training accuracy', color='blue')
plt.plot(np.arange(1,epok +1,1),training_history.history['val_accuracy'], label='Validation accuracy', color='red')

plt.legend()

plt.show()
# On réalise une prédiction avec le modèle
y_pred = model.predict(X_test_top)
y_pred_propre = y_pred.argmax(axis=-1)
cnf_matrix = confusion_matrix(y_test_top,y_pred_propre)

classes = range(0,6)

plt.figure()
plt.imshow(cnf_matrix,interpolation ='nearest',cmap = 'Blues')
plt.title('Matrice de confusion')
plt.colorbar()

tick_marks = np.arange(len(classes))
plt.xticks(tick_marks,classes)
plt.yticks(tick_marks,classes)

for i in range(cnf_matrix.shape[0]):
    for j in range(cnf_matrix.shape[1]):
        plt.text(i,j,cnf_matrix[i,j],horizontalalignment ='center')
        
plt.show()<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.1051937780121276, 'fraction_numerical': 0.007118375955707883, 'mean_word_length': 5.684581497797357, 'pattern_counts': {'":': 0, '<': 55, '<?xml version=': 0, '>': 55, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '12', 'dir': 'jupyter-structured-clean-dedup', 'id': '35419', 'license': 'MIT', 'n_tokens_mistral': 2819, 'n_tokens_neox': 2766, 'n_words': 665, 'path': 'RNN - Game of throne - Qui parle .ipynb', 'repo_name': 'LaurentHP-Martin/Training', 'size': '7635'}