Welcome to Melusine’s documentation !¶

This package aims to be the reference in the processing and modelization of French email data. The project has been developed by MAIF.
Company |
GitHub Account |
Website |
---|---|---|
![]() |
Melusine¶

Free software: Apache Software License 2.0
Documentation: https://melusine.readthedocs.io.
Overview¶
Melusine is a high-level Python library for emails classification and feature extraction, written in Python and capable of running on top of Scikit-Learn, Keras or Tensorflow. It was developed with a focus on emails written in french.
- Use Melusine if you need a library which :
Supports both convolutional networks and recurrent networks, as well as combinations of the two.
Runs seamlessly on CPU and GPU.
Melusine is compatible with Python 3.6 (<=2.3.2), Python 3.7 and Python 3.8.
Release Notes¶
Release 2.3.5¶
- Bug fix:
PR139: Fix config search with a recursive paramater.
Release 2.3.4¶
- New features:
PR 128: A Lemmatizer class has been added by the Société Générale team! Lemmatizer object is compatible with sklearn pipelines and is built around an sklearn Transformer. Details can be found in [tutorial 04](https://github.com/MAIF/melusine/blob/master/tutorial/tutorial04_nlp_tools.ipynb) and [08](https://github.com/MAIF/melusine/blob/master/tutorial/tutorial08_full_pipeline_detailed.ipynb)
PR 132: A `Stemmer`class has been added. Details can also be found in tutorial 04.
PR 132: A `DeterministicEmojiFlagger`class has been added to flag emojis. Details can be found in tutorial 08.
- Updates:
Python 3.6 is no longer supported for tensorflow compatibility issues. Melusine is now running with Tensorflow 2.8
PR 121: Add the return of the histogram after the training (train.py)
PR 120: Tokenizer can now be specified in a NeuralModel init. Embedding and Phraser classes have been simplified. See [tutorial 04](https://github.com/MAIF/melusine/blob/master/tutorial/tutorial04_nlp_tools.ipynb)
PR 120: Config has been split into different functionalities files that can be found in /melusine/config/parameters for more readability. See [tutorial 10](https://github.com/MAIF/melusine/blob/master/tutorial/tutorial10_conf_file.ipynb)
PR 120: A text_flagger`and a `token_flagger class have been created to give you a glimpse of the library redesign but are not called yet.
- Bug fix:
PR 124: fixing purge of dict_attr keys while saving bert models (train.py)
Issue 126: fixing initialisation of bert_tokenizer for cross validation (train.py)
Release 2.3.2¶
- Updates:
Compatibility with python 3.7 and 3.8
Optional dependencies (viz, transformers, all)
Specify custom configurations with environment variable MELUSINE_CONFIG_DIR
Use any number of JSON and YAML files for configurations
(instead of just one config file)
- Bug fix:
Fixed bug when training transformers model without meta features
Release 2.3¶
- New features:
Added a class ExchangeConnector to interact with an Exchange Mailbox
Added new tutorial tutorial14_exchange_connector to demonstrate the usage of the ExchangeConnector class
- Updates:
Gensim upgrade ([4.0.0](https://github.com/RaRe-Technologies/gensim/releases))
Propagate modifications stemming from the Gensim upgrade (code and tutorials)
Package deployment : switch from Travis CI to Github actions
Release 2.0¶
- New features:
Attentive Neural Networks are now available. :tada: We propose you an original Transformer architecture as well as pre-trained BERT models (Camembert and Flaubert)
Tutorial 13 will explain you how to get started with these models and attempt to compare them.
Validation data can now be used to train models (See fit function from NeuralModel for usage)
The activation function can now be modified to adapt to your needs (See NeuralModel init for usage)
Release 1.10.0¶
- Updates:
Melusine is now running with Tensorflow 2.2
Release 1.9.6¶
- New features:
Flashtext library is now used to flag names instead of regex. It allows a faster computation.
Release 1.9.5¶
- New features:
An Ethics Guide is now available to evaluate AI projects, with guidelines and questionnaire. The questionnaire is based on criteria derived in particular from the work of the European Commission and grouped by categories.
Melusine also offers an easy and nice dashboard app with StreamLit. The App contains exploratory dashboard on the email dataset and a more specific study on discrimination between the dataset and a neural model classification.
The Melusine package¶

This package is designed for the preprocessing, classification and automatic summarization of emails written in french. 3 main subpackages are offered :
prepare_email : to preprocess and clean the emails.
summarizer : to extract keywords from an email.
models : to classify e-mails according to categories pre-defined defined by the user.
2 other subpackages are offered as building blocks :
nlp_tools : to provide classic NLP tools such as tokenizer, phraser and embeddings.
utils : to provide a TransformerScheduler class to build your own transformer and integrate it into a scikit-learn Pipeline.
An other subpackage is also provided to manage, modify or add parameters such as : regular expressions, keywords, stopwords, etc.
config : contains ConfigJsonReader class to setup and handle a conf.json file. This JSON file is the core of this package since it’s used by different submodules to preprocess the data.
Getting started : 30 seconds to Melusine¶
Importing Melusine¶
To use Melusine in a project:
import melusine
Input data : Email DataFrame¶
The basic requirement to use Melusine is to have an input e-mail DataFrame with the following columns:
body : Body of an email (single message or conversation history)
header : Header of an email
date : Reception date of an email
from : Email address of the sender
to (optional): Email address of the recipient
label (optional): Label of the email for a classification task (examples: Business, Spam, Finance or Family)
body |
header |
date |
from |
to |
label |
---|---|---|---|---|---|
Thank you.\nBye,\nJohn |
Re: Your order |
jeudi 24 mai 2018 11 h 49 CEST |
?? |
To import the test dataset:
from melusine.data.data_loader import load_email_data
df_email = load_email_data()
Pre-processing pipeline¶
A working pre-processing pipeline is given below:
from sklearn.pipeline import Pipeline
from melusine.utils.transformer_scheduler import TransformerScheduler
from melusine.prepare_email.manage_transfer_reply import check_mail_begin_by_transfer, update_info_for_transfer_mail, add_boolean_answer, add_boolean_transfer
from melusine.prepare_email.build_historic import build_historic
from melusine.prepare_email.mail_segmenting import structure_email
from melusine.prepare_email.body_header_extraction import extract_last_body
from melusine.prepare_email.cleaning import clean_body
ManageTransferReply = TransformerScheduler(
functions_scheduler=[
(check_mail_begin_by_transfer, None, ['is_begin_by_transfer']),
(update_info_for_transfer_mail, None, None),
(add_boolean_answer, None, ['is_answer']),
(add_boolean_transfer, None, ['is_transfer'])
])
EmailSegmenting = TransformerScheduler(
functions_scheduler=[
(build_historic, None, ['structured_historic']),
(structure_email, None, ['structured_body'])
])
Cleaning = TransformerScheduler(
functions_scheduler=[
(extract_last_body, None, ['last_body']),
(clean_body, None, ['clean_body'])
])
prepare_data_pipeline = Pipeline([
('ManageTransferReply', ManageTransferReply),
('EmailSegmenting', EmailSegmenting),
('Cleaning', Cleaning),
])
df_email = prepare_data_pipeline.fit_transform(df_email)
Phraser and Tokenizer pipeline¶
A pipeline to train and apply the phraser end tokenizer is given below:
from melusine.nlp_tools.phraser import Phraser
from melusine.nlp_tools.tokenizer import Tokenizer
tokenizer = Tokenizer (input_column='clean_body', output_column="tokens")
df_email = tokenizer.fit_transform(df_email)
phraser = Phraser(
input_column='tokens',
output_column='phrased_tokens',
threshold=5,
min_count=2
)
_ = phraser.fit(df_email)
df_email = phraser.transform(df_email)
Embeddings training¶
An example of embedding training is given below:
from melusine.nlp_tools.embedding import Embedding
embedding = Embedding(
tokens_column='tokens',
size=300,
workers=4,
min_count=3
)
embedding.train(df_email)
Metadata pipeline¶
A pipeline to prepare the metadata is given below:
from melusine.prepare_email.metadata_engineering import MetaExtension, MetaDate, Dummifier
metadata_pipeline = Pipeline([
('MetaExtension', MetaExtension()),
('MetaDate', MetaDate()),
('Dummifier', Dummifier())
])
df_meta = metadata_pipeline.fit_transform(df_email)
Keywords extraction¶
An example of keywords extraction is given below:
from melusine.summarizer.keywords_generator import KeywordsGenerator
keywords_generator = KeywordsGenerator()
df_email = keywords_generator.fit_transform(df_email)
Classification¶
The package includes multiple neural network architectures including CNN, RNN, Attentive and pre-trained BERT Networks. An example of classification is given below:
from sklearn.preprocessing import LabelEncoder
from melusine.models.neural_architectures import cnn_model
from melusine.models.train import NeuralModel
X = df_email.drop(['label'], axis=1)
y = df_email.label
le = LabelEncoder()
y = le.fit_transform(y)
pretrained_embedding = embedding
nn_model = NeuralModel(architecture_function=cnn_model,
pretrained_embedding=pretrained_embedding,
text_input_column='clean_body')
nn_model.fit(X, y)
y_res = nn_model.predict(X)
Glossary¶
Pandas dataframes columns¶
Because Melusine manipulates pandas dataframes, the naming of the columns is imposed. Here is a basic glossary to provide an understanding of each columns manipulated. Initial columns of the dataframe:
body : the body of the email. It can be composed of a unique message, a history of messages, a transfer of messages or a combination of history and transfers.
header : the subject of the email.
date : the date the email has been sent. It corresponds to the date of the last message of the email has been written.
from : the email address of the author of the last message of the email.
to : the email address of the recipient of the last message.
Columns added by Melusine:
is_begin_by_transfer : boolean, indicates if the email is a direct transfer. In that case it is recommended to update the value of the initial columns with the informations of the message transferred.
is_answer : boolean, indicates if the email contains a history of messages
is_transfer : boolean, indicates if the email is a transfer (in that case it does not have to be a direct transfer).
structured_historic : list of dictionaries, each dictionary corresponds to a message of the email. The first dictionary corresponds to the last message (the one that has been written) while the last dictionary corresponds to the first message of the history. Each dictionary has two keys :
meta : to access the metadata of the message as a string.
text : to access the message itself as a string.
structured_body : list of dictionaries, each dictionary corresponds to a message of the email. The first dictionary corresponds to the last message (the one that has been written) while the last dictionary corresponds to the first message of the history. Each dictionary has two keys :
meta : to access the metadata of the message as a dictionary. The dictionary has three keys:
date : the date of the message.
from : the email address of the author of the message.
to : the email address of the recipient of the message.
text : to access the message itself as a dictionary. The dictionary has two keys:
header : the subject of the message.
structured_text : the different parts of the message segmented and tagged as a list of dictionaries. Each dictionary has two keys:
part : to access the part of the message as a string.
tags : to access the tag of the part of the message.
last_body : string, corresponds to the part of the last message of the email that has been tagged as “BODY”.
clean_body : string, corresponds a cleaned last_body.
clean_header : string, corresponds to a cleaned header.
clean_text : string, concatenation of clean_header and clean_body.
tokens : list of strings, corresponds to a tokenized column, by default clean_text.
keywords : list of strings, corresponds to the keywords of extracted from the tokens column.
stemmed_tokens : list of strings, corresponds to a stemmed column, by default stemmed_tokens.
lemma_spacy_sm : string, corresponds to a lemmatized column.
lemma_lefff : string, corresponds to a lemmatized column.
Motivation & history¶
Origin of the project¶
MAIF, being one of the leading mutual insurance companies in France, receives daily a large volume of emails from its clients and is under pressure to reply to their requests as efficiently as possible. As such an efficient routing system is of the upmost importance to assign each emails to its right entity. However the previously outdated routing system put the company under ever increasing difficulties to fulfill its pledge. In order to face up to this challenge, MAIF has implemented a new routing system based on state-of-the-art NLP and Deep Learning techniques that would classify each email under the right label according to its content and extract the relevant information to help the MAIF counsellors processing the emails.
Ambitions of the project¶
Melusine is the first Open Source and free-of-use solution dedicated specifically to the qualification of e-mails written in french. The ambition of this Python package is to become a reference, but also to live in the French NLP community by federating users and contributors. Initially developed to answer the problem of routing e-mails received by the MAIF, the solution was implemented using state-of-the-art techniques in Deep Learning and NLP. Melusine can be interfaced with Scikit-Learn: it offers the user the possibility to train his own classification and automatic summarization model according to the constraints of his problem.
Why Melusine ?¶
Following MAIF’s tradition to name its open source packages after deities, it was chosen to release this package under the name of Melusine as an homage to a legend from the local folklore in the Poitou region in France where MAIF is historically based.
Credits¶
This package was created with Cookiecutter and the audreyr/cookiecutter-pypackage project template.
Installation¶
Stable release¶
To install melusine, run this command in your terminal:
$ pip install melusine
This is the preferred method to install melusine, as it will always install the most recent stable release.
If you don’t have pip installed, this Python installation guide can guide you through the process.
Optional dependencies¶
When running Melusine in production, users may want to limit the number of packages installed. For this purpose, Melusine makes use of optional dependencies. The command pip install melusine installs only the mandatory dependencies. Optional dependencies can be install as follows:
pip install melusine[viz] : Installs plotly and streamlit for visualization purposes
pip install melusine[exchange] : Installs exchangelib to connect Melusine with an Outlook Exchange mailbox
pip install melusine[transformers] : Installs transformers to train BERT-like models
pip install melusine[all] : Installs all the dependencies
From sources¶
The sources for melusine can be downloaded from the Github repo.
You can either clone the public repository:
$ git clone https://github.com/MAIF/melusine
Or download the tarball:
$ curl -OL https://github.com/MAIF/melusine
Once you have a copy of the source, you can install it with:
$ python setup.py install
Usage¶
To use melusine in a project:
import melusine
Melusine input data : Email DataFrames¶
The basic requirement to use Melusine is to have an input e-mail DataFrame with the following columns:
body
: Body of an email (single message or conversation historic)
header
: Header of an email
date
: Reception date of an email
from
: Email address of the sender
to
: Email address of the recipient
label
(optional) : Label of the email for a classification task (examples: Business, Spam, Finance or Family)
body |
header |
date |
from |
to |
label |
---|---|---|---|---|---|
Thank you.\nBye,\nJohn |
Re: Your order |
jeudi 24 mai 2018 11 h 49 CEST |
A |
In the examples presented below, a toy email DataFrame containing anonymized emails is used. The toy DataFrame can be loaded as follows:
from melusine.melusine.utils.data_loader import load_email_data
df_emails = load_email_data()
df_emails.head()
Prepare email subpackage : Basic usage¶
A common pre-processing step is to check whether an e-mail is an answer or not. This can be done in Melusine with the function add_boolean_answer:
from melusine.prepare_email.manage_transfer_reply import add_boolean_answer
df_emails['is_answer'] = df_emails.apply(add_boolean_answer, axis=1)
A new column is_answer
is created containing a boolean variable:
True if the message is an answer
False if the message is not an answer
body |
header |
is_answer |
---|---|---|
Happy Birthday Bill!! |
Birthday |
False |
Thank you |
Re: Birthday |
True |
Create an email pre-processing pipeline¶
An email pre-processing pipeline takes an email DataFrame as input and executes a sequence of Transformers on every email in the DataFrame. The recommended way to create a pre-processing pipeline with Melusine is to:
Wrap pre-processing functions in TransformerScheduler objects.
Use a Scikit-Learn Pipeline object to chain transformers
Once the pipeline has been set-up, the pre-processing of an email DataFrame is straightforward:
>>> df_emails_preprocessed = pipeline.fit_transform(df_emails)
TransformerScheduler class¶
Functions can be wrapped in a TransformerScheduler object that can be integrated into an execution Pipeline.
TransformerScheduler
objects are compatible with the scikit-learn API
(they have fit and transform methods).
A TransformerScheduler
object is initialized with a functions_scheduler argument.
The functions_scheduler argument is a list of tuples containing information about the desired pre-processing functions.
Each tuple describe an individual function and should contain the following elements:
A function
A tuple with the function’s arguments (if no arguments are required, use None or an empty tuple)
A column(s) name list returned by the function (if no arguments are required, use None or an empty list)
The code below describes the definition of a transformer:
from melusine.utils.transformer_scheduler import TransformerScheduler
melusine_transformer = TransformerScheduler(
functions_scheduler=[
(my_function_1, (argument1, argument2), ['return_col_A']),
(my_function_2, None, ['return_col_B', 'return_col_C'])
(my_function_3, (argument1, ), None),
mode='apply_by_multiprocessing',
n_jobs=4)
])
The other parameters of the TransformerScheduler class are:
mode
(optional): Define mode to apply function along a row axis (axis=1) If set to ‘apply_by_multiprocessing’, it uses multiprocessing tool to parallelize computation. Possible values are ‘apply’ (default) and ‘apply_by_multiprocessing’
n_jobs
(optional): Number of cores used for computation. Default value, 1. Possible values are integers ranging from 1 (default) to the number of cores available for computation
A TransformerScheduler
can be used independently or included in a scikit pipeline (recommended):
>>> # Used independently
>>> df_emails = melusine_transformer.fit_transform(df_emails)
>>> # Used in a scikit pipeline
>>> from sklearn.pipeline import Pipeline
>>> pipeline = Pipeline([('MelusineTransformer', melusine_transformer)])
>>> df_emails = pipeline.fit_transform(df_emails)
The fit_transform method returns a DataFrame with new features (new columns)
body |
header |
return_col_A |
return_col_B |
return_col_C |
return_col_D |
---|---|---|---|---|---|
Happy Birthday Bill!! |
Birthday |
new_feature_A |
new_feature_B |
new_feature_C |
new_feature_D |
Thank you |
Re: Birthday |
new_feature_A |
new_feature_B |
new_feature_C |
new_feature_D |
Chaining transformers in a scikit-learn pipeline¶
Once all the desired functions and transformers have been defined, transformers can be chained in a Scikit-Learn Pipeline. The code below describes the definition of a pipeline:
from sklearn.pipeline import Pipeline
pipeline = Pipeline([
('TransformerName1', TransformerObject1),
('TransformerName2', TransformerObject2),
('TransformerName3', TransformerObject3),
])
Example of a working pipeline¶
A working pre-processing pipeline is given below:
from sklearn.pipeline import Pipeline
from melusine.utils.transformer_scheduler import TransformerScheduler
from melusine.prepare_email.manage_transfer_reply import add_boolean_answer, add_boolean_transfer
from melusine.prepare_email.build_historic import build_historic
from melusine.prepare_email.mail_segmenting import structure_email
ManageTransferReply = TransformerScheduler(
functions_scheduler=[
(add_boolean_answer, None, ['is_answer']),
(add_boolean_transfer, None, ['is_transfer'])
])
HistoricBuilder = TransformerScheduler(
functions_scheduler=[
(build_historic, None, ['structured_historic']),
])
Segmenting = TransformerScheduler(
functions_scheduler=[
(structure_email, None, ['structured_body'])
])
prepare_data_pipeline = Pipeline([
('ManageTransferReply', ManageTransferReply),
('HistoricBuilder', HistoricBuilder),
('Segmenting', Segmenting),
])
df_emails = prepare_data_pipeline.fit_transform(df_emails)
In this example, the pre-processing functions applied are:
add_boolean_answer : Email is an answer (True/False)
add_boolean_transfer : Email is transferred (True/False)
build_historic : When email is a conversation, reconstructs the individual message historic
structure_email : Splits parts of each messages in historic and tags them (tags: Hello, Body, Greetings, etc)
Create a custom email pre-processing function¶
Creating a custom pre-processing function and adding it to a pre-processing pipeline can be done easily with Melusine. Two main requirements are:
Make the function compatible with the pandas apply method
- First argument should be ‘row’ (Row of an email DataFrame)
>>> def my_function(row, arg1, arg2):Example: row[‘header’] will contain the header of a message
Make sure to call existing columns of the DataFrame
Don’t call row[‘is_answer’] before the ‘is_answer’ column has been created
The following example creates a custom function to count the occurrence of a word in the body of an email:
import pandas as pd
from sklearn.pipeline import Pipeline
from melusine.utils.transformer_scheduler import TransformerScheduler
from melusine.prepare_email.manage_transfer_reply import add_boolean_answer, add_boolean_transfer
# Create a fake email Dataframe
df_duck = pd.DataFrame({
"body" : ["Lion Duck Pony", "Duck Pony Pony", "Duck Duck Pony"],
"header" : ["zoo report", "Tr : zoo report", "Re : zoo report"]
})
# Define a custom function
def count_word_occurrence_in_body(row, word):
all_word_list = row["body"].lower().split()
word_occurence = all_word_list.count(word)
return word_occurence
# Wrap function in a transformer
CountWordOccurrence = TransformerScheduler(
functions_scheduler=[
(count_word_occurrence_in_body, ("duck",), ['duck_count']),
(count_word_occurrence_in_body, ("pony",), ['pony_count']),
])
# Create a second transformer with regular Melusine functions
ManageTransferReply = TransformerScheduler(
functions_scheduler=[
(add_boolean_answer, None, ['is_answer']),
(add_boolean_transfer, None, ['is_transfer'])
])
# Chain transformers in a pipeline
prepare_data_pipeline = Pipeline([
('CountWordOccurrence', CountWordOccurrence), # Transformer with custom functions
('ManageTransferReply', ManageTransferReply), # Transformer with regular Melusine functions
])
# Pre-process input DataFrame
df_duck_prep = prepare_data_pipeline.fit_transform(df_duck)
body |
header |
duck_count |
pony_count |
is_answer |
is_transfer |
---|---|---|---|---|---|
Lion Duck Pony |
zoo report |
1 |
1 |
False |
False |
Duck Duck Pony |
Re : zoo report |
2 |
1 |
True |
False |
Duck Pony Pony |
Tr : zoo report |
1 |
2 |
False |
False |
Note : It is totally fine to mix regular and custom functions in a transformer.
Testing a function on a single email¶
Since all pre-processing functions are made compatible with pandas apply function, a function can be tested on a single email. In the example below, the function add_boolean_answer is tested on a single email:
from melusine.prepare_email.manage_transfer_reply import add_boolean_answer
email_index = 2
email_is_answer = add_boolean_answer(df_emails.iloc[email_index])
print("Message %d is an answer: %r" %(email_index, email_is_answer))
Output:
"Message 2 is an answer: True"
NLP tools subpackage¶
The different classes of the NLP tools subpackage are described in this section.
Phraser¶
The Melusine Phraser class transforms common multi-word expressions into single elements:
>>> new york -> new_york
To train a Melusine Phraser
(which is based on a Gensim Phraser),
the input email DataFrame should contain a ‘clean_body’ column which can be created with the clean_body function.
In the example below, a Phraser
is trained on a toy DataFrame:
import pandas as pd
from melusine.nlp_tools.phraser import Phraser
from melusine.nlp_tools.phraser import phraser_on_text
phraser = Phraser()
df_new_york = pd.DataFrame({
'clean_body' : ["new york is so cool", "i love new york", "new york city"]
})
phraser.train(df_new_york)
df_new_york['clean_body'] = df_new_york['clean_body'].apply(phraser_on_text, args=(phraser,))
# Save the Phraser instance to disk
phraser.save('./pretrained_phraser.pickle')
# Load the Phraser
pretrained_phraser = Phraser().load('./pretrained_phraser.pickle')
In reality, a training set with only 3 emails is too small to train a Phraser
.
For illustrative purpose, the table below shows the expected output.
clean_body |
clean_body_new |
---|---|
new york is so cool |
new_york is so cool |
i love new york |
i love new_york |
new york city |
new_york city |
The specific parameters of the Phraser class are:
common_terms
: list of stopwords to be ignored (default value = stopword list from NLTK)
threshold
: threshold to select collocations
min_count
: minimum count of word to be selected as collocation
Tokenizer¶
A tokenizer splits a sentence-like string into a list of sub-strings (tokens). The Melusine Tokenizer class is based on a NLTK regular expression tokenizer which uses a regular expression (regex) pattern to tokenize the text:
import pandas as pd
from melusine.nlp_tools.tokenizer import Tokenizer
df_tok = pd.DataFrame({
'clean_body' : ["hello, i'm here to tokenize text. bye"],
'clean_header' : ["re: hello"],
})
tokenizer = Tokenizer(input_column='clean_body')
df_tok = tokenizer.fit_transform(df_tok)
A new column tokens
is created with a list of the tokens extracted from the text data.
clean_body |
clean_header |
tokens |
---|---|---|
hello, i’m here to tokenize text. bye |
re: hello |
[‘hello’, ‘i’, ‘here’, ‘tokenize’, ‘text’, ‘bye’] |
The specific parameters of the Tokenizer class are:
stopwords
: list of keywords to be ignored (this list can be defined in the conf file)
stop_removal
: True if stopwords should be removed, else False
Embeddings¶
With a regular representation of words, there is one dimension for each word in the vocabulary (set of all the words in a text corpus). The computational cost of NLP tasks, such as training a neural network model, based on such a high dimensional space can be prohibitive. Word embeddings are abstract representations of words in a lower dimensional vector space. One of the advantages of word embeddings is thus to save computational cost.
The Melusine Embedding class uses the Gensim Word2Vec module to train a word2vec model.
The trained Embedding
object will be used in the Models subpackage to train a Neural Network to classify emails.
The code below illustrates how the Embedding
class works. It should be noted that, in practice, to train a word embedding model, a lot of emails are required:
import pandas as pd
from melusine.nlp_tools.embedding import Embedding
df_embeddings = pd.DataFrame({
'clean_body' : ["word text word text data word text"],
'clean_header' : ["re: hello"],
})
embedding = Embedding(input_column='clean_body', min_count=3)
embedding.train(df_embeddings)
# Save the trained Embedding instance to disk
embedding.save('./pretrained_embedding.pickle')
# Load the trained Embedding instance
pretrained_embedding = Embedding().load('./pretrained_embedding.pickle')
# Use trained Embedding to initialise the Neural Network Model
# The definition of a neural network model is not discussed in this section
# nn_model = NeuralModel("...", pretrained_embedding=pretrained_embedding, "...")
Summarizer subpackage¶
The main item of the Summarizer subpackage is the KeywordGenerator class.
The KeywordGenerator
class extracts relevant keywords in the text data based on a tf-idf score.
Requirements on the input DataFrame to use a KeywordGenerator
:
KeywordGenerator requires a ‘tokens’ column which can be generated with a Tokenizer
Keywords can then be extracted as follows:
import pandas as pd
from melusine.summarizer.keywords_generator import KeywordsGenerator
from melusine.nlp_tools.tokenizer import Tokenizer
df_zoo = pd.DataFrame({
'clean_body' : ["i like lions and ponys and gorillas", "i like ponys and tigers", "i like tigers and lions", "i like raccoons and unicorns"],
'clean_header' : ["things i like", "things i like", "things i like", "things i like"]
})
tokenizer = Tokenizer(input_column='clean_body')
# Create the 'tokens' column
df_zoo = tokenizer.fit_transform(df_zoo)
keywords_generator = KeywordsGenerator(n_max_keywords=2, stopwords=['like'])
# Fit keyword generator on the text data corpus (using the tokens column)
keywords_generator.fit(df_zoo)
# Extract relevant keywords
keywords_generator.transform(df_zoo)
In the text data of the example, some words are very common such as “i”, “like” or “things”, whereas other words are rare, such as “raccoons”. The keyword generator gives priority to rare words in the keyword extraction process:
clean_body |
clean_header |
tokens |
keywords |
---|---|---|---|
i like lions and ponies and gorillas |
things i like |
[things, i, i, lions, and, ponies, and, gorillas] |
[lions, ponys] |
i like ponies and tigers |
things i like |
[things, i, i, ponies, and, tigers] |
[ponies, tigers] |
i like tigers and lions |
things i like |
[things, i, i, tigers, and, lions] |
[tigers, lions] |
i like raccoons and unicorns |
things i like |
[things, i, i, raccoons, and, unicorns] |
[raccoons, unicorns] |
The specific parameters of the KeywordGenerator class are:
max_tfidf_features
: size of vocabulary for tfidf
keywords
: list of keyword to be extracted in priority (this list can be defined in the conf file)
stopwords
: list of keywords to be ignored (this list can be defined in the conf file)
resample
: when DataFrame contains a ‘label’ column, balance the dataset by resampling
n_max_keywords
: maximum number of keywords to be returned for each email
n_min_keywords
: minimum number of keywords to be returned for each email
threshold_keywords
: minimum tf-idf score for a word to be selected as keyword
Models subpackage¶
The main item of the Models subpackage is the NeuralModel class.
The NeuralModel
creates a Neural Network that can be trained and used to classify emails.
The minimum input features required by the NeuralModel
class are the following:
An email DataFrame with:
an integer ‘label’ column (a label encoder can be used to convert class names into integers)
a ‘clean_text’ column with text data
An instance of the Embedding class (Trained word embedding model)
The code below shows a minimal working example for Email Classification using a NeuralModel instance (a much larger training set is required to obtain meaningful results):
import pandas as pd
# Prepare email
from melusine.utils.transformer_scheduler import TransformerScheduler
from melusine.prepare_email.manage_transfer_reply import \
check_mail_begin_by_transfer, update_info_for_transfer_mail, add_boolean_answer, add_boolean_transfer
from melusine.prepare_email.build_historic import build_historic
from melusine.prepare_email.mail_segmenting import structure_email
from melusine.prepare_email.body_header_extraction import extract_last_body, extract_header
from melusine.prepare_email.cleaning import clean_body, clean_header
from melusine.prepare_email.metadata_engineering import MetaDate, MetaExtension, Dummifier
# Scikit-Learn API
from sklearn.pipeline import Pipeline
# NLP tools
from melusine.nlp_tools.phraser import Phraser
from melusine.nlp_tools.phraser import phraser_on_body
from melusine.nlp_tools.phraser import phraser_on_header
from melusine.nlp_tools.tokenizer import Tokenizer
from melusine.nlp_tools.embedding import Embedding
# Summarizer
from melusine.summarizer.keywords_generator import KeywordsGenerator
# Models
from melusine.models.train import NeuralModel
from melusine.models.neural_architectures import cnn_model
# Load toy email data
from utils.data_loader import load_email_data
df_emails = load_email_data()
# Transformer object to manage transfers and replies
ManageTransferReply = TransformerScheduler(
functions_scheduler=[
(check_mail_begin_by_transfer, None, ['is_begin_by_transfer']),
(update_info_for_transfer_mail, None, None),
(add_boolean_answer, None, ['is_answer']),
(add_boolean_transfer, None, ['is_transfer'])
]
)
# Transformer object to segment the different messages in the email, parse their metadata and
# tag the different part of the messages
Segmenting = TransformerScheduler(
functions_scheduler=[
(build_historic, None, ['structured_historic']),
(structure_email, None, ['structured_body'])
]
)
# Transformer object to extract the body of the last message of the email and clean it as
# well as the header
LastBodyHeaderCleaning = TransformerScheduler(
functions_scheduler=[
(extract_last_body, None, ['last_body']),
(clean_body, None, ['clean_body']),
(clean_header, None, ['clean_header'])
]
)
# Transformer object to apply the phraser on the texts
phraser = Phraser().load('./phraser.pickle')
PhraserTransformer = TransformerScheduler(
functions_scheduler=[
(phraser_on_body, (phraser,), ['clean_body']),
(phraser_on_header, (phraser,), ['clean_header'])
]
)
# Tokenizer object
tokenizer = Tokenizer(input_column="clean_body")
# Full preprocessing pipeline
PreprocessingPipeline = Pipeline([
('ManageTransferReply', ManageTransferReply),
('Segmenting', Segmenting),
('LastBodyHeaderCleaning', LastBodyHeaderCleaning),
('PhraserTransformer', PhraserTransformer),
('tokenizer', tokenizer)
])
# Apply preprocessing pipeline to DataFrame
df_emails = PreprocessingPipeline.fit_transform(df_emails)
# Pipeline to extract dummified metadata
MetadataPipeline = Pipeline([
('MetaExtension', MetaExtension()),
('MetaDate', MetaDate()),
('Dummifier', Dummifier())
])
# Apply MetaData processing pipeline to DataFrame
df_meta = MetadataPipeline.fit_transform(df_emails)
# Keywords extraction
keywords_generator = KeywordsGenerator(n_max_keywords=3)
df_emails = keywords_generator.fit_transform(df_emails)
# Train an embedding with the 'clean_body' data
pretrained_embedding = Embedding(input_column='clean_body', min_count=3)
pretrained_embedding.train(df_emails)
# Create a 'clean_text' column from the 'clean_header' and 'clean_body' columns
df_emails['clean_text'] = df_emails['clean_header']+'. '+df_emails['clean_body']
# Create a training set DataFrame with MetaData + the 'clean_text' columns
X = pd.concat([df_emails['clean_text'],df_meta],axis=1)
# The 'label' column contains target labels for email classification
# Labels should be encoded ('Family', 'Work', 'Sport' => 1, 2, 3)
from sklearn.preprocessing import LabelEncoder
y = df_emails['label']
le = LabelEncoder()
y = le.fit_transform(y)
# CNN model with 'clean_text' as text_input and 'extension', 'dayofweek', 'hour', 'min'
# as metadata input
nn_model = NeuralModel(neural_architecture_function=cnn_model,
pretrained_embedding=pretrained_embedding,
text_input_column="clean_text",
meta_input_list=['extension', 'dayofweek', 'hour', 'min'],
n_epochs=10)
# Train the Neural Network model
nn_model.fit(X,y)
# Predict labels on the training dataset
y_res = nn_model.predict(X)
# Decode prediction results (1, 2, 3 => 'Family', 'Work', 'Sport')
y_res = le.inverse_transform(y_res)
# Print results
print(y_res)
The specific parameters of the NeuralModel class are:
neural_architecture_function
: function which returns a Neural Network Model instance from Keras
pretrained_embedding
: pretrained embedding (Embedding class object)
text_input_column
: input text column to consider for the model (Example: ‘clean_body’)
meta_input_list
: list of the names of the columns containing the metadata If empty list or None the model is used without metadata Default value, [‘extension’, ‘dayofweek’, ‘hour’, ‘min’]
vocab_size
: size of vocabulary for neural network model
seq_size
: maximum size of input for neural model
loss
: loss function for training (Default ‘categorical_crossentropy’)
batch_size
: size of batches for the training of the neural network model
n_epochs
: number of epochs for the training of the neural network model
We integrate 3 main classifier neural networks, respectively recurrent, convolutional and attentive. Each of the proposed architecture employs a distinct mathematical operation.
Recurrent Neural Network Classifier (RNN)¶
RNN are traditionally used with textual data as they are specifically designed to handle sequentially structured data. Inputs are sequentially computed given a cell operation, generally a LSTM or GRU cell. at each step, the current input as well as the output from the previous step are used to compute the next hidden state. The proposed architecture includes a 2-layers bidirectional GRU networks. The network last hidden state is used as the final sentence embedding.

Convolutional Neural Network Classifier (CNN)¶
CNN uses multiple filters to distinguish patterns in data. Such filters are assembled across the hidden layers to build more complex patterns and structures. The last layer should therefor capture a global and generic representation of the data. In our architecture, we use a two hidden layers CNN with respectively 200 filters for each hidden layer. The last hidden states are aggregated using a max pooling operation.

Attentive Neural Network Classifier¶
Attentive-based neural networks are fairly new in the NLP community but results are extremely promising. They rely on the self-attention operation which computes hidden states as a weighted sum from the inputs. As the multiple filters in the CNN architecture, the multi-branch attention aggregate multiple attention operation to capture various properties from the input. Such operation is easily perform on GPU infrastructure. We propose an architecture inspired from previously introduced RNN and CNN architecture with a two layers multi-branch attention module follow by a max pooling operation.

BERT Neural Network Classifier¶
We also propose a wrap-up for the popular pre-trained bert architecture. Bidirectional Encoder Representations from Transformers (BERT) take into account the context for each occurrence of a given word and will provide a contextualized embedding that will be different according to the sentence. However, we only use the first word embedding, usually called the classification token in our classifier model. We made available the two trending French models Camembert and Flaubert.

Use a custom config file¶
To optimize Melusine for your needs, a custom configuration file may be used. Through a custom configuration file, the user can specify parameters such as:
- Custom keywordsList of keywords that Melusine should focus on
Example: extract keywords with the KeywordExtractor
- Custom stopwordsList of stopwords that Melusine should ignore
Example: tokenize sentences with a Tokenizer
- Custom regular expressions (regex)regex used in the melusine functions
Example: Regex to detect that a message is a reply
The following code shows how to specify a custom configuration file:
from melusine.config.config import ConfigJsonReader
conf = ConfigJsonReader()
# Print the path to the current configuration file
with open(conf.path_ini_file_, 'r') as ini_file:
print(ini_file.read())
# Print the content of the current configuration file
conf_dict = conf.get_config_file()
print(conf_dict) # will print the json
# Set a new path to the configuration file
conf.set_config_path(file_path='my/path/conf.json')
# Print the new path to the configuration file
with open(conf.path_ini_file_, 'r') as ini_file:
print(ini_file.read())
# Print the content of the new configuration file
conf_dict = conf.get_config_file()
print(conf_dict) # will print the json
It is also possible to go back to the original configuration file:
from melusine.config.config import ConfigJsonReader
conf = ConfigJsonReader()
conf.reset_config_path()
Warning : the configuration file is loaded by the different modules (Tokenizer, KeywordExtractor, etc) during the import, therefore, for the new configuration file to be effective, the code / kernel should be restarted after each modification of the configuration file.
Use a custom name file¶
While working with text data, names might undergo specific processing:
stopword processing : if names don’t need to be identified, they may be discarded during the text processing
flagging : if names need to be identified but not specifically, names may be replaced with a name_flag (bob -> flag_name)
By default, Melusine identifies names using an explicit list of names available in a file (‘melusine/config/names.csv’). The default name list was adapted from a name dataset publicly available on the french government website. This list contains first names given to children (french or not) born in France between 1900 and 2018.
Melusine users may specify a custom name list using a custom ‘names.csv’ file.
The following code shows how to specify a custom configuration file:
import os
import pandas as pd
from melusine.config.config import ConfigJsonReader
conf = ConfigJsonReader()
# Print the path to the current name file
with open(conf.path_ini_file_, 'r') as ini_file:
print(ini_file.read())
# Print the current name list
conf_dict = conf.get_config_file()
print(conf_dict['words_list']['names'][:5])
### Use a custom name file
# 1. Create a new (custom) name file
# - The file should be a csv file with a column called `Name`
# 2. Set the new file as the current Melusine name file with open(conf.path_ini_file_, 'r') as ini_file:
# Set a new path to the configuration file
# Create a name DataFrame
df_names = pd.DataFrame({'Name' : ['Daenerys', 'Tyrion', 'Jon', 'Raegar']})
# Path to the new name.csv file
new_path = os.path.join(os.getcwd(), 'data', 'names.csv')
# Save new name.csv file
df_names.to_csv(new_path, encoding="latin-1", sep=";", index=False)
# Set a new path to the name file in Melusine
conf.set_name_file_path(file_path=new_path)
# Print the new path to the name file
with open(conf.path_ini_file_, 'r') as ini_file:
print(ini_file.read())
# Print the new file list
conf_dict = conf.get_config_file()
print(conf_dict['words_list']['names'][:5])
It is possible to go back to the original name file:
from melusine.config.config import ConfigJsonReader
conf = ConfigJsonReader()
conf.reset_name_file_path()
conf_dict = conf.get_config_file()
print(conf_dict['words_list']['names'][:5])
Warning : the name file is loaded by the different modules (Tokenizer, KeywordExtractor, etc) during the import, therefore, for the new name file to be effective, the code / kernel should be restarted after each modification of the name file.
Package dependencies¶
Melusine works with Python versions from 3.6 to 3.8. It builds on top of following packages:
pandas
scikit-learn
flashtext
gensim
tensorflow
joblib
unidecode
Melusine API¶
Utils subpackage melusine.utils
¶
TODO : ADD DESCRIPTION OF THE SUBPACKAGE
List of submodules¶
TransformerScheduler melusine.utils.transformer_scheduler
¶
Useful class to define its own transformer using specific functions in a specific order to apply along a row of DataFrame (axis=1).
It is compatible with scikit-learn API (i.e. contains fit, transform methods).
- class melusine.utils.transformer_scheduler.TransformerScheduler(functions_scheduler, mode='apply', n_jobs=1, progress_bar=True, copy=True, verbose=0)[source]¶
Bases:
sklearn.base.BaseEstimator
,sklearn.base.TransformerMixin
This class aims to provide a good way to define its own transformer. It takes a list of function defined in a specific order to apply along a row of DataFrame (axis=1). Transformer returned is compatible with scikit-learn API (i.e. contains fit, transform methods).
- Parameters
- functions_schedulerlist of tuples, (function, tuple, list)
List of function to be applied in a specific order. Each element of the list has to be defined as follow: (function, argument(s) used by the function (optional), colname(s) returned (optional))
- modestr {‘apply’, ‘apply_by_multiprocessing’}, optional
Define mode to apply function along a row axis (axis=1). Default value, ‘apply’. If set to ‘apply_by_multiprocessing’, it uses multiprocessing tool to parallelize computation.
- n_jobsint, optional
Number of cores used for computation. Default value, 1.
- progress_barboolean, optional
Whether to print a progress bar from tqdm package. Default value, True. Works only when mode is set to ‘apply_by_multiprocessing’.
- copyboolean, optional
Make a copy of DataFrame. Default value, True.
- verboseint, optional
Verosity mode, print loggers. Default value, 0.
Examples
>>> from melusine.utils.transformer_scheduler import TransformerScheduler
>>> MelusineTransformer = TransformerScheduler( >>> functions_scheduler=[ >>> (my_function_1, (argument1, argument2), ['return_col_A']), >>> (my_function_2, None, ['return_col_B', 'return_col_C']) >>> (my_function_3, (), ['return_col_D']) >>> ])
- Attributes
- function_scheduler, mode, n_jobs, progress_bar
- static apply_dict(X_, func_, args_=None, cols_=None, **kwargs)[source]¶
Apply a function on a dictionary.
- Parameters
- X_dict,
Data on which transformations are applied.
- args_list or tuple
List of arguments of the function to apply
- cols_list or tuple
List of columns created by the transformation
- func_func
Function to apply
- Returns
- dict
- static apply_pandas(X_, func_, args_=None, cols_=None, **kwargs)[source]¶
Apply a function on a pandas DataFrame.
- Parameters
- X_pandas.DataFrame,
Data on which transformations are applied.
- args_list or tuple
List of arguments of the function to apply
- cols_list or tuple
List of columns created by the transformation
- func_func
Function to apply
- Returns
- pandas.DataFrame
Multiprocessing melusine.utils.multiprocessing
¶
- melusine.utils.multiprocessing.apply_by_multiprocessing(df, func, **kwargs)[source]¶
Apply a function along an axis of the DataFrame using multiprocessing.
- Parameters
- dfpd.DataFrame
DataFrame where the function is applied
- funcfunction to apply
- Returns
- pd.DataFrame
Returns the DataFrame with the function applied.
Streamer melusine.utils.streamer
¶
PrintParts melusine.utils.printer
¶
Prepare_email subpackage melusine.prepare_email
¶

List of submodules¶
Transfer & Reply melusine.prepare_email.manage_transfer_reply
¶
- melusine.prepare_email.manage_transfer_reply.add_boolean_answer(row)[source]¶
Compute boolean Series which return True if the “header” starts with given regex ‘transfer_subject’, False if not.
To be used with methods such as: apply(func, axis=1) or apply_by_multiprocessing(func, axis=1, **kwargs).
- Parameters
- rowrow of pd.Dataframe, columns [‘header’]
- Returns
- pd.Series
Examples
>>> import pandas as pd >>> data = pd.read_pickle('./tutorial/data/emails_anonymized.pickle') >>> # data contains a 'header' column
>>> from melusine.prepare_email.manage_transfer_reply import add_boolean_answer >>> add_boolean_answer(data.iloc[0]) # apply for 1 sample >>> data.apply(add_boolean_answer, axis=1) # apply to all samples
- melusine.prepare_email.manage_transfer_reply.add_boolean_transfer(row)[source]¶
Compute boolean Series which return True if the “header” starts with given regex ‘answer_subject’, False if not.
To be used with methods such as: apply(func, axis=1) or apply_by_multiprocessing(func, axis=1, **kwargs).
- Parameters
- rowrow of pd.Dataframe, columns [‘header’]
- Returns
- pd.Series
Examples
>>> import pandas as pd >>> data = pd.read_pickle('./tutorial/data/emails_anonymized.pickle') >>> # data contains a 'header' column
>>> from melusine.prepare_email.manage_transfer_reply import add_boolean_transfer >>> add_boolean_transfer(data.iloc[0]) # apply for 1 sample >>> data.apply(add_boolean_transfer, axis=1) # apply to all samples
- melusine.prepare_email.manage_transfer_reply.check_mail_begin_by_transfer(row)[source]¶
Compute boolean Series which return True if the “body” starts with given regex ‘begin_transfer’, False if not.
To be used with methods such as: apply(func, axis=1) or apply_by_multiprocessing(func, axis=1, **kwargs).
- Parameters
- rowrow of pd.Dataframe, columns [‘body’]
- Returns
- pd.Series
Examples
>>> import pandas as pd >>> data = pd.read_pickle('./tutorial/data/emails_anonymized.pickle') >>> # data contains a 'body' column
>>> from melusine.prepare_email.manage_transfer_reply import check_mail_begin_by_transfer >>> check_mail_begin_by_transfer(data.iloc[0]) # apply for 1 sample >>> data.apply(check_mail_begin_by_transfer, axis=1) # apply to all samples
- melusine.prepare_email.manage_transfer_reply.update_info_for_transfer_mail(row)[source]¶
Extracts and updates informations from forwarded mails, such as: body, from, to, header, date. - It changes the header by the initial subject (extracted from forward email). - It removes the header from emails’ body.
To be used with methods such as: apply(func, axis=1) or apply_by_multiprocessing(func, axis=1, **kwargs).
- Parameters
- rowrow of pd.Dataframe,
- columns [‘body’, ‘header’, ‘from’, ‘to’, ‘date’, ‘is_begin_by_transfer’]
- Returns
- pd.DataFrame
Examples
>>> import pandas as pd >>> from melusine.prepare_email.manage_transfer_reply import check_mail_begin_by_transfer >>> data = pd.read_pickle('./tutorial/data/emails_anonymized.pickle') >>> data['is_begin_by_transfer'] = data.apply(check_mail_begin_by_transfer, axis=1) >>> # data contains columns ['from', 'to', 'date', 'header', 'body', 'is_begin_by_transfer']
>>> from melusine.prepare_email.manage_transfer_reply import update_info_for_transfer_mail >>> update_info_for_transfer_mail(data.iloc[0]) # apply for 1 sample >>> data.apply(update_info_for_transfer_mail, axis=1) # apply to all samples
Cleaning melusine.prepare_email.cleaning
¶
Cleaning of the body and the header
- melusine.prepare_email.cleaning.clean_body(row, flags=True)[source]¶
- Clean body column. The cleaning involves the following operations:
Cleaning the text
Removing the multiple spaces
Flagging specific items (postal code, phone number, date…)
- Parameters
- rowrow of pandas.Dataframe object,
Data contains ‘last_body’ column.
- flagsboolean, optional
True if you want to flag relevant info, False if not. Default value, True.
- Returns
- row of pandas.DataFrame object or pandas.Series if apply to all DF.
- melusine.prepare_email.cleaning.clean_header(row, flags=True)[source]¶
- Clean the header column. The cleaning involves the following operations:
Removing the transfers and answers indicators
Cleaning the text
Flagging specific items (postal code, phone number, date…)
- Parameters
- rowrow of pandas.Dataframe object,
Data contains ‘header’ column.
- flagsboolean, optional
True if you want to flag relevant info, False if not. Default value, True.
- Returns
- row of pd.DataFrame object or pandas.Series if apply to all DF.
- melusine.prepare_email.cleaning.clean_text(text)[source]¶
- Clean a string. The cleaning involves the following operations:
Putting all letters to lowercase
Removing all the accents
Removing all line breaks
Removing all symbols and punctuations
Removing the multiple spaces
- Parameters
- textstr
- Returns
- str
- melusine.prepare_email.cleaning.flag_items(text, flags=True)[source]¶
- Flag relevant information
ex : amount, phone number, email address, postal code (5 digits)..
- Parameters
- textstr,
Body content.
- flagsboolean, optional
True if you want to flag relevant info, False if not. Default value, True.
- Returns
- str
- melusine.prepare_email.cleaning.remove_accents(text, use_unidecode=False)[source]¶
Remove accents from text Using unidecode is more powerful but much more time consuming Exemple: the joined ‘ae’ character is converted to ‘a’ + ‘e’ by unidecode while it is suppressed by unicodedata.
- melusine.prepare_email.cleaning.remove_multiple_spaces_and_strip_text(text)[source]¶
Remove multiple spaces, strip text, and remove ‘-’, ‘*’ characters.
- Parameters
- textstr,
Header content.
- Returns
- str
- melusine.prepare_email.cleaning.remove_superior_symbol(text)[source]¶
Remove superior and inferior symbols from text
Build Email Historic melusine.prepare_email.build_historic
¶
- melusine.prepare_email.build_historic.build_historic(row)[source]¶
Rebuilds and structures historic of emails from the whole contents. Function has to be applied with apply method of a DataFrame along an axis=1. For each email of the historic, it segments the body into 2 different parts (2 keys of dict):
- {‘text’: extract raw text without metadata,
‘meta’: get transition from the ‘transition_list’ defined in the conf.json }.
- Parameters
- rowrow,
A pandas.DataFrame row object with ‘body’ column.
- Returns
- list
Examples
>>> import pandas as pd >>> data = pd.read_pickle('./tutorial/data/emails_anonymized.pickle') >>> # data contains a 'body' column
>>> from melusine.prepare_email.build_historic import build_historic >>> build_historic(data.iloc[0]) # apply for 1 sample >>> data.apply(build_historic, axis=1) # apply to all samples
Email Segmenting melusine.prepare_email.mail_segmenting
¶
- melusine.prepare_email.mail_segmenting.split_message_to_sentences(text, sep_='(.*?[;.,?!])')[source]¶
Split each sentences in a text
- melusine.prepare_email.mail_segmenting.structure_email(row)[source]¶
1. Splits parts of each messages in historic and tags them. For example a tag can be hello, body, greetings etc 2. Extracts the meta informations of each messages
To be used with methods such as: apply(func, axis=1) or apply_by_multiprocessing(func, axis=1, **kwargs).
- Parameters
- rowrow of pd.Dataframe, apply on column [‘structured_historic’]
- Returns
- list of dictsone dict per message
Examples
>>> import pandas as pd >>> from melusine.prepare_email.build_historic import build_historic >>> data = pd.read_pickle('./tutorial/data/emails_anonymized.pickle') >>> data['structured_historic'] = data.apply(build_historic, axis=1) >>> # data contains column ['structured_historic']
>>> from melusine.prepare_email.mail_segmenting import structure_email >>> structure_email(data.iloc[0]) # apply for 1 sample >>> data.apply(structure_email, axis=1) # apply to all samples
- melusine.prepare_email.mail_segmenting.structure_message(message)[source]¶
Splits parts of a message and tags them. For example a tag can be hello, body, greetings etc Extracts the meta informations of the message
- Parameters
- messagedict
- Returns
- dict
- melusine.prepare_email.mail_segmenting.structure_meta(meta)[source]¶
Extract meta informations (date, from, to, header) from string meta
- Parameters
- metastr
- Returns
- tuple(dict, string)
- melusine.prepare_email.mail_segmenting.tag(string)[source]¶
Tags a string.
- Parameters
- stringstr,
- Returns
- tupleslist of tuples and boolean
- melusine.prepare_email.mail_segmenting.tag_parts_message(text)[source]¶
Splits message into sentences, tags them and merges two sentences in a row having the same tag.
- Parameters
- textstr,
- Returns
- list of tuples
- melusine.prepare_email.mail_segmenting.tag_sentence(sentence, default='BODY')[source]¶
Tag a sentence. If the sentence cannot be tagged it will tag the subsentences
- Parameters
- sentencestr,
- Returns
- list of tuplessentence, tag
- melusine.prepare_email.mail_segmenting.tag_signature(row, token_threshold=5)[source]¶
Function to be called after the mail_segmenting function as it requires a “structured_body” column. This function detects parts of a message that qualify as “signature”. Exemples of parts qualifying as signature are sender name, company name, phone number, etc.
The methodology to detect a signature is the following: - Look for a THANKS or GREETINGS part indicating that the message is approaching the end - Check the length of the following message parts currently tagged as “BODY” - (The maximum number of words is specified through the variable “signature_token_threshold”) - If ALL the “ending parts” contain few words => tag them as “SIGNATURE” parts - Otherwise : cancel the signature tagging
- Parameters
- rowpd.Series
Row of an email DataFrame
- Returns
- structured_bodyUpdated structured body
Process Email Metadata melusine.prepare_email.metadata_engineering
¶
- class melusine.prepare_email.metadata_engineering.Dummifier(columns_to_dummify=['extension', 'dayofweek', 'hour', 'min', 'attachment_type'], copy=True)[source]¶
Bases:
sklearn.base.BaseEstimator
,sklearn.base.TransformerMixin
Transformer to dummifies categorial features and list of . Compatible with scikit-learn API.
- class melusine.prepare_email.metadata_engineering.MetaAttachmentType(topn_extension=100)[source]¶
Bases:
sklearn.base.BaseEstimator
,sklearn.base.TransformerMixin
Transformer which creates ‘type’ feature extracted from regex in metadata. It extracts types of attached files.
Compatible with scikit-learn API.
- class melusine.prepare_email.metadata_engineering.MetaDate(regex_date_format='\\w+ (\\d+) (\\w+) (\\d{4}) (\\d{2}) h (\\d{2})', date_format='%d/%m/%Y %H:%M')[source]¶
Bases:
sklearn.base.BaseEstimator
,sklearn.base.TransformerMixin
- Transformer which creates new features from dates such as:
hour
minute
dayofweek
Compatible with scikit-learn API.
- Parameters
- date_formatstr, optional
Regex to extract date from text.
- date_formatstr, optional
A date format.
- class melusine.prepare_email.metadata_engineering.MetaExtension(topn_extension=100)[source]¶
Bases:
sklearn.base.BaseEstimator
,sklearn.base.TransformerMixin
Transformer which creates ‘extension’ feature extracted from regex in metadata. It extracts extension of mail adresses.
Compatible with scikit-learn API.
Extract Email Body & Header melusine.prepare_email.body_header_extraction
¶
- melusine.prepare_email.body_header_extraction.extract_body(message_dict)[source]¶
Extracts the body from a message dictionary.
- Parameters
- message_dictdict
- Returns
- str
- melusine.prepare_email.body_header_extraction.extract_header(message_dict)[source]¶
Extracts the header from a message dictionary.
- Parameters
- message_dictdict
- Returns
- str
- melusine.prepare_email.body_header_extraction.extract_last_body(row)[source]¶
Extracts the body from the last message of the conversation. The conversation is structured as a dictionary.
To be used with methods such as: apply(func, axis=1) or apply_by_multiprocessing(func, axis=1, **kwargs).
- Parameters
- message_dictdict
- Returns
- str
Nlp_tools subpackage melusine.nlp_tools
¶
TODO : ADD DESCRIPTION OF THE SUBPACKAGE
List of submodules¶
Tokenizer melusine.nlp_tools.tokenizer
¶
- class melusine.nlp_tools.tokenizer.RegexTokenizer(tokenizer_regex: str = '\\w+(?:[\\?\\-\\"_]\\w+)*', stopwords: Optional[List[str]] = None)[source]¶
Bases:
object
- FILENAME = 'tokenizer.json'¶
Tokenize text using a regex split pattern.
Phraser melusine.nlp_tools.phraser
¶
Embedding melusine.nlp_tools.embedding
¶
- class melusine.nlp_tools.embedding.Embedding(tokens_column=None, workers=40, random_seed=42, iter=15, size=300, method='word2vec_cbow', min_count=100)[source]¶
Bases:
object
Class to train embeddings with Word2Vec algorithm. Attributes ———- word2id: dict,
Word vocabulary (key: word, value: word_index.
- embeddingGensim KeyedVector Instance,
Gensim KeyedVector Instance relative to the specific trained or imported embedding.
- methodstr,
- One of the following :
“word2vec_sg” : Trains a Word2Vec Embedding using the Skip-Gram method (usually takes a long time).
“word2vec_cbow” : Trains a Word2Vec Embedding using the Continuous Bag-Of-Words method.
“lsa_docterm” : Trains an Embedding by using an SVD on a Document-Term Matrix.
“lsa_tfidf” : Trains an Embedding by using an SVD on a TF-IDFized Document-Term Matrix.
- train_paramsdict,
- Additional parameters for the embedding training. Check the following documentation :
gensim.models.Word2Vec for Word2Vec Embeddings
sklearn.decomposition.TruncatedSVD for LSA Embeddings
If left untouched, the default training values will be kept from the aforementioned packages.
>>> from melusine.nlp_tools.embedding import Embedding >>> embedding = Embedding() >>> embedding.train(X) # noqa >>> embedding.save(filepath) # noqa >>> embedding = Embedding().load(filepath) # noqa
Stemmer melusine.nlp_tools.stemmer
¶
Lemmatizer melusine.nlp_tools.lemmatizer
¶
Emoji Flagger melusine.nlp_tools.emoji_flagger
¶
Summarizer subpackage melusine.summarizer
¶
TODO : ADD DESCRIPTION OF THE SUBPACKAGE
List of submodules¶
KeywordsGenerator melusine.summarizer.keywords_generator
¶
- class melusine.summarizer.keywords_generator.KeywordsGenerator(max_tfidf_features=10000, keywords=['keyword'], stopwords=['au', 'aux', 'avec', 'ce', 'ces', 'dans', 'de', 'des', 'du', 'elle', 'en', 'et', 'eux', 'il', 'je', 'la', 'le', 'leur', 'lui', 'ma', 'mais', 'me', 'même', 'mes', 'moi', 'mon', 'ne', 'nos', 'notre', 'nous', 'on', 'ou', 'par', 'pas', 'pour', 'qu', 'que', 'qui', 'sa', 'se', 'ses', 'son', 'sur', 'ta', 'te', 'tes', 'toi', 'ton', 'tu', 'un', 'une', 'vos', 'votre', 'vous', 'c', 'd', 'j', 'l', 'à', 'm', 'n', 's', 't', 'y', 'été', 'étée', 'étées', 'étés', 'étant', 'étante', 'étants', 'étantes', 'suis', 'es', 'est', 'sommes', 'êtes', 'sont', 'serai', 'seras', 'sera', 'serons', 'serez', 'seront', 'serais', 'serait', 'serions', 'seriez', 'seraient', 'étais', 'était', 'étions', 'étiez', 'étaient', 'fus', 'fut', 'fûmes', 'fûtes', 'furent', 'sois', 'soit', 'soyons', 'soyez', 'soient', 'fusse', 'fusses', 'fût', 'fussions', 'fussiez', 'fussent', 'ayant', 'ayante', 'ayantes', 'ayants', 'eu', 'eue', 'eues', 'eus', 'ai', 'as', 'avons', 'avez', 'ont', 'aurai', 'auras', 'aura', 'aurons', 'aurez', 'auront', 'aurais', 'aurait', 'aurions', 'auriez', 'auraient', 'avais', 'avait', 'avions', 'aviez', 'avaient', 'eut', 'eûmes', 'eûtes', 'eurent', 'aie', 'aies', 'ait', 'ayons', 'ayez', 'aient', 'eusse', 'eusses', 'eût', 'eussions', 'eussiez', 'eussent', 'nan', 'aaliyah', 'aalyah', 'aaron', 'abbas', 'abbes', 'abby', 'abbygaelle', 'abbygaelle', 'abd', 'abd-el', 'abdallah', 'abdel', 'abdel-aziz', 'abdel-hakim', 'abdel-kader', 'abdel-karim', 'abdel-malik', 'abdelali', 'abdelatif', 'abdelaziz', 'abdelghani', 'abdelhadi', 'abdelhafid', 'abdelhak', 'abdelhakim', 'abdelhalim', 'abdelhamid', 'abdelilah', 'abdeljalil', 'abdelkader', 'abdelkarim', 'abdelkrim', 'abdellah', 'abdellatif', 'abdelmadjid', 'abdelmajid', 'abdelmalek', 'abdelmalik', 'abdelnour', 'abdelrahim', 'abdelrahman', 'abdelrahmane', 'abdelrani', 'abdelwahab', 'abdenour', 'abderahim', 'abderahman', 'abderahmane', 'abderrahim', 'abderrahman', 'abderrahmane', 'abderrazak', 'abdeslam', 'abdessamad', 'abdon', 'abdou', 'abdoul', 'abdoulaye', 'abdoullah', 'abdourahmane', 'abdul', 'abdullah', 'abdurrahman', 'abed', 'abel', 'abigael', 'abigaelle', 'abigail', 'abigael', 'abigaelle', 'abigail', 'abilio', 'abir', 'abla', 'abou', 'aboubacar', 'aboubakar', 'aboubakr', 'abraham', 'aby', 'abygael', 'abygaelle', 'abygael', 'abygaelle', 'acelya', 'achille', 'achour', 'achraf', 'ada', 'adalbert', 'adaline', 'adam', 'adama', 'adame', 'adan', 'adda', 'adel', 'adela', 'adelaide', 'adelaide', 'adele', 'adelia', 'adelie', 'adelin', 'adelina', 'adeline', 'adelino', 'adelphine', 'adelyne', 'adem', 'aden', 'adham', 'adib', 'adil', 'adile', 'adja', 'adnan', 'adnane', 'adolphe', 'adolphine', 'adonis', 'adrian', 'adriana', 'adriane', 'adrianna', 'adriano', 'adriel', 'adrien', 'adrienne', 'adele', 'adelaide', 'adelia', 'adelie', 'aedan', 'ael', 'aela', 'aelia', 'aelig', 'aelys', 'afaf', 'afif', 'afonso', 'agate', 'agatha', 'agathe', 'aglae', 'aglaee', 'aglae', 'agnan', 'agnes', 'agostinho', 'agostino', 'aharon', 'ahcene', 'ahlam', 'ahlame', 'ahlem', 'ahmad', 'ahmadou', 'ahmed', 'ahmet', 'aicha', 'aida', 'aidan', 'aiden', 'aileen', 'aima', 'aimad', 'aiman', 'aimane', 'aimen', 'aimeric', 'aimery', 'aimie', 'aimy', 'aina', 'ainhoa', 'ainoa', 'aisha', 'aissa', 'aissam', 'aissata', 'aissatou', 'aisse', 'aissetou', 'aiya', 'aiyana', 'akif', 'akil', 'akila', 'akim', 'akima', 'akin', 'akli', 'akram', 'aksel', 'aksil', 'alaa', 'alae', 'alaia', 'alain', 'alais', 'alan', 'alana', 'alane', 'alanis', 'alann', 'alaric', 'alassane', 'alais', 'alba', 'alban', 'albane', 'albanie', 'alberic', 'albert', 'alberta', 'alberte', 'albertine', 'alberto', 'albin', 'albina', 'albine', 'albino', 'alcide', 'alcime', 'alda', 'aldo', 'aldric', 'alec', 'alejandro', 'alek', 'aleksandar', 'aleksandra', 'alen', 'alena', 'alenzo', 'alesia', 'alessandra', 'alessandro', 'alessia', 'alessio', 'aleth', 'alex', 'alexa', 'alexander', 'alexandra', 'alexandre', 'alexandrine', 'alexandro', 'alexandru', 'alexane', 'alexanne', 'alexi', 'alexia', 'alexian', 'alexiane', 'alexie', 'alexina', 'alexine', 'alexis', 'alexy', 'alexya', 'alexys', 'aleyna', 'alfonso', 'alfred', 'alfreda', 'alfredine', 'alfredo', 'ali', 'alia', 'alice', 'alicia', 'alicya', 'alida', 'alienor', 'aliette', 'alim', 'alima', 'alin', 'alina', 'aline', 'aliocha', 'aliou', 'alioune', 'alisa', 'alise', 'alisee', 'alisha', 'alison', 'alisone', 'alissa', 'alissia', 'alisson', 'alistair', 'alix', 'alixe', 'alixia', 'aliya', 'aliyah', 'aliza', 'alize', 'alizea', 'alizee', 'alize', 'alizee', 'alienor', 'allain', 'allan', 'allen', 'allison', 'allisson', 'allya', 'allyah', 'allyson', 'alma', 'almire', 'alois', 'aloise', 'alon', 'alonso', 'alonzo', 'aloys', 'aloyse', 'alois', 'aloise', 'alper', 'alperen', 'alpha', 'alphonse', 'alphonsine', 'alric', 'alrick', 'althea', 'alvaro', 'alvin', 'alvina', 'alvine', 'alvyn', 'alwena', 'alwenna', 'alwin', 'aly', 'alya', 'alyah', 'alyana', 'alycia', 'alyette', 'alys', 'alysee', 'alyson', 'alyssa', 'alyssia', 'alysson', 'alyzee', 'alena', 'amable', 'amadeo', 'amadou', 'amael', 'amaelle', 'amaia', 'amal', 'amale', 'amalia', 'amalya', 'amance', 'amand', 'amanda', 'amande', 'amandine', 'amane', 'amani', 'amar', 'amara', 'amaria', 'amaryllis', 'amaury', 'amaya', 'amayas', 'amael', 'amaia', 'amber', 'ambre', 'ambrine', 'ambroise', 'ambroisine', 'amed', 'amede', 'amedee', 'amel', 'amele', 'amelia', 'amelie', 'amelien', 'amelina', 'ameline', 'amelle', 'amely', 'amelya', 'americo', 'amicie', 'amin', 'amina', 'aminata', 'amine', 'amir', 'amira', 'amjad', 'ammar', 'amna', 'amor', 'amory', 'amos', 'amour', 'amparo', 'amy', 'amelia', 'amelie', 'amelya', 'ana', 'ana-maria', 'anabel', 'anabela', 'anabella', 'anabelle', 'anae', 'anael', 'anaele', 'anaelle', 'anais', 'anaise', 'anakin', 'anas', 'anass', 'anasse', 'anastase', 'anastasia', 'anastasie', 'anastassia', 'anasthasia', 'anasthasie', 'anatole', 'anaya', 'anae', 'anae', 'anael', 'anaelle', 'anaia', 'anais', 'ancelin', 'anderson', 'andgel', 'andoche', 'andoni', 'andrea', 'andreane', 'andreas', 'andreea', 'andrei', 'andreia', 'andres', 'andrew', 'andria', 'andry', 'andre', 'andrea', 'andreas', 'andree', 'andy', 'anes', 'aness', 'anette', 'anfel', 'ange', 'ange-marie', 'angel', 'angela', 'angele', 'angelica', 'angelie', 'angelika', 'angelin', 'angelina', 'angeline', 'angelino', 'angelique', 'angelita', 'angella', 'angelle', 'angelo', 'angie', 'angus', 'angy', 'angele', 'angela', 'angelina', 'angeline', 'angelique', 'angelo', 'anh', 'ani', 'ania', 'anic', 'anice', 'anicet', 'anicette', 'anicia', 'anick', 'anie', 'aniela', 'anik', 'anil', 'anir', 'anis', 'anisa', 'anise', 'aniss', 'anissa', 'anisse', 'anissia', 'anita', 'anja', 'anjali', 'ann', 'anna', 'anna-maria', 'anna-rose', 'annabel', 'annabella', 'annabelle', 'annael', 'annaelle', 'annah', 'annaick', 'annaig', 'annaik', 'annaelle', 'anne', 'anne-carole', 'anne-caroline', 'anne-catherine', 'anne-charlotte', 'anne-christine', 'anne-claire', 'anne-claude', 'anne-cecile', 'anne-celine', 'anne-elisabeth', 'anne-elise', 'anne-emmanuelle', 'anne-fleur', 'anne-flore', 'anne-florence', 'anne-france', 'anne-francoise', 'anne-frederique', 'anne-gaelle', 'anne-gaelle', 'anne-helene', 'anne-isabelle', 'anne-julie', 'anne-laure', 'anne-laurence', 'anne-line', 'anne-lise', 'anne-louise', 'anne-lucie', 'anne-lyse', 'anne-marie', 'anne-rose', 'anne-sarah', 'anne-solene', 'anne-sophie', 'anne-sylvie', 'anne-therese', 'anne-valerie', 'anne-yvonne', 'anneliese', 'annelise', 'annelyse', 'annet', 'annette', 'annic', 'annick', 'annie', 'annie-claude', 'annie-france', 'annik', 'annissa', 'annita', 'annoncia', 'annonciade', 'anny', 'anonyme', 'anouar', 'anouchka', 'anouck', 'anouk', 'anselme', 'anta', 'anthea', 'anthelme', 'anthime', 'anthonin', 'anthony', 'anthyme', 'anthea', 'antoine', 'antoinette', 'anton', 'antone', 'antonella', 'antoni', 'antonia', 'antonie', 'antonietta', 'antonin', 'antonina', 'antonine', 'antonino', 'antonio', 'antonn', 'antony', 'antton', 'anwar', 'any', 'anya', 'anys', 'anyssa', 'aodren', 'apoline', 'apollinaire', 'apolline', 'apollonie', 'appolinaire', 'appoline', 'appolonie', 'april', 'aram', 'aramis', 'arcade', 'archange', 'archibald', 'arda', 'areski', 'arezki', 'argan', 'ari', 'aria', 'ariana', 'ariane', 'arianne', 'arie', 'ariel', 'arielle', 'arif', 'arij', 'aris', 'ariste', 'aristide', 'arlene', 'arlette', 'arman', 'armance', 'armand', 'armande', 'armandine', 'armando', 'armantine', 'armel', 'armele', 'armelle', 'armonie', 'armony', 'arnaud', 'arnauld', 'arnault', 'arno', 'arnold', 'arnould', 'aron', 'arone', 'aronn', 'arsene', 'arsene', 'arthemise', 'arthur', 'arthus', 'artur', 'arturo', 'artus', 'arwa', 'arwen', 'arwenn', 'ary', 'arya', 'arzu', 'ascension', 'ashley', 'ashton', 'asia', 'asiya', 'aslan', 'asli', 'asma', 'asmaa', 'asmae', 'asmin', 'assa', 'assad', 'assane', 'assetou', 'assia', 'assil', 'assile', 'assim', 'assiya', 'assma', 'assunta', 'assya', 'aston', 'astou', 'astrid', 'astride', 'asya', 'atef', 'athanase', 'athena', 'athenais', 'athina', 'athena', 'athenais', 'atika', 'atilla', 'attilio', 'aubane', 'aubert', 'aubin', 'aubry', 'aude', 'aude-marie', 'audeline', 'audran', 'audray', 'audren', 'audrey', 'audric', 'audrina', 'audry', 'augusta', 'auguste', 'augustin', 'augustina', 'augustine', 'augusto', 'aurane', 'aure', 'aurea', 'aurel', 'aurele', 'aurelia', 'aurelie', 'aurelien', 'aureline', 'aurelio', 'aurely', 'auria', 'aurian', 'auriana', 'auriane', 'aurianne', 'aurora', 'aurore', 'aurele', 'aurelia', 'aurelie', 'aurelien', 'austin', 'auxane', 'auxence', 'ava', 'aveline', 'avi', 'avit', 'awa', 'awen', 'awena', 'axel', 'axele', 'axelle', 'aya', 'ayaan', 'ayah', 'ayan', 'ayana', 'ayanna', 'ayat', 'ayaz', 'aydan', 'ayden', 'aydin', 'ayhan', 'ayla', 'aylan', 'aylane', 'ayleen', 'aylin', 'ayline', 'ayman', 'aymane', 'aymar', 'aymeline', 'aymen', 'aymene', 'aymeric', 'aymerick', 'aymerik', 'ayna', 'aynur', 'ayoub', 'ayoube', 'ayron', 'ayrton', 'ayse', 'aysegul', 'aysel', 'aysenur', 'aysun', 'ayyoub', 'azad', 'azdine', 'azeddine', 'azedine', 'azelie', 'azeline', 'azilis', 'aziliz', 'azilys', 'aziz', 'aziza', 'azize', 'azra', 'azzeddine', 'azzedine', 'azziz', 'azelie', 'aelia', 'aelys', 'ael', 'aelys', 'aicha', 'aida', 'aidan', 'aiden', 'aina', 'ainhoa', 'aisha', 'aissa', 'aissata', 'aissatou', 'baba', 'babacar', 'babette', 'babylas', 'bachir', 'bader', 'badia', 'badis', 'badr', 'badra', 'badre', 'badreddine', 'badredine', 'bafode', 'bahar', 'bahia', 'bahija', 'bakari', 'bakary', 'bakhta', 'balkis', 'balla', 'balthazar', 'bandiougou', 'bao', 'baptiste', 'baptistin', 'baptistine', 'baran', 'barbara', 'barbe', 'baris', 'barnabe', 'barnabe', 'barthelemy', 'barthelemy', 'basil', 'basile', 'basma', 'bassem', 'bassma', 'bastian', 'bastien', 'bathilde', 'batiste', 'batuhan', 'baudoin', 'baudouin', 'baya', 'bayane', 'bayram', 'bayron', 'bazile', 'beatrix', 'beatriz', 'bechir', 'bekir', 'belaid', 'belgacem', 'belinay', 'belinda', 'belkacem', 'bella', 'ben', 'benamar', 'benedict', 'benedicte', 'benito', 'benjamin', 'benjamine', 'benji', 'benjy', 'benoist', 'benoit', 'benoite', 'benoni', 'benoit', 'beranger', 'berangere', 'berat', 'berenger', 'berengere', 'berenice', 'berfin', 'berivan', 'berkan', 'berkay', 'bernadette', 'bernadin', 'bernadine', 'bernard', 'bernardin', 'bernardine', 'bernardo', 'bertha', 'berthe', 'berthilde', 'bertille', 'bertin', 'bertrand', 'bertrande', 'beryl', 'besma', 'betina', 'betsy', 'bettina', 'betty', 'betul', 'beverley', 'beverly', 'beya', 'beyza', 'bianca', 'bibi', 'bienaime', 'bilal', 'bilel', 'billal', 'billel', 'billie', 'billy', 'bineta', 'binta', 'bintou', 'bixente', 'blaise', 'blanche', 'blandine', 'blessing', 'bleuenn', 'bleuette', 'blondine', 'bluette', 'bob', 'bocar', 'bochra', 'bogdan', 'boleslaw', 'bonaventure', 'boniface', 'bonnie', 'boris', 'boualem', 'boubacar', 'boubakar', 'boubaker', 'boubou', 'bouchra', 'boumediene', 'boumedienne', 'bouziane', 'bouzid', 'brad', 'bradley', 'brady', 'brahim', 'brahima', 'brandon', 'brandy', 'brayan', 'brayton', 'brenda', 'brendan', 'brendon', 'brewen', 'briac', 'brian', 'briana', 'brianna', 'brice', 'brieg', 'brieuc', 'brigitte', 'britany', 'britney', 'brittany', 'bronislaw', 'bronislawa', 'brooklyn', 'bruce', 'bruna', 'brune', 'brunehilde', 'brunella', 'brunette', 'bruno', 'bryan', 'bryana', 'bryanna', 'bryce', 'btissam', 'bunyamin', 'burak', 'busra', 'byron', 'beatrice', 'belinda', 'benedicte', 'berangere', 'berengere', 'beryl', 'berenice', 'caitlin', 'caleb', 'cali', 'calie', 'calista', 'calixte', 'callie', 'callista', 'calliste', 'cally', 'calogera', 'calogero', 'calvin', 'caly', 'calypso', 'calysta', 'camel', 'camelia', 'camellia', 'cameron', 'camerone', 'camil', 'camila', 'camilia', 'camilla', 'camille', 'camillia', 'camilo', 'camron', 'camelia', 'can', 'canan', 'candice', 'candida', 'candide', 'candido', 'candie', 'candy', 'candyce', 'candys', 'canelle', 'cannelle', 'cansu', 'cantin', 'capucine', 'cara', 'carene', 'carina', 'carine', 'carinne', 'carl', 'carla', 'carla-marie', 'carline', 'carlo', 'carlos', 'carlotta', 'carly', 'carlyne', 'carmel', 'carmela', 'carmele', 'carmelina', 'carmelle', 'carmelo', 'carmen', 'carmine', 'carol', 'carol-anne', 'carolane', 'carole', 'carole-anne', 'carolina', 'caroline', 'caroll', 'carolle', 'carolyn', 'carolyne', 'casey', 'casimir', 'casimira', 'cassandra', 'cassandre', 'cassidy', 'cassie', 'cassiopee', 'cassiopee', 'cassy', 'castille', 'cataldo', 'cataleya', 'catalina', 'catarina', 'caterina', 'catharina', 'catheline', 'catherina', 'catherine', 'cathia', 'cathie', 'cathleen', 'cathy', 'catia', 'caty', 'cecilia', 'cecilie', 'cecilien', 'cedric', 'cedrick', 'cedrik', 'cedrine', 'celena', 'celeste', 'celestin', 'celestine', 'celia', 'celian', 'celiane', 'celie', 'celien', 'celina', 'celine', 'celinie', 'celio', 'cellia', 'celya', 'celyan', 'cem', 'cendrine', 'cengiz', 'ceren', 'cerena', 'cerine', 'cerise', 'cesaire', 'cesar', 'cesarine', 'ceyda', 'ceylan', 'ceylin', 'chabane', 'chad', 'chaden', 'chadi', 'chadia', 'chafia', 'chafik', 'chafika', 'chahd', 'chahid', 'chahin', 'chahinaz', 'chahine', 'chahinez', 'chahineze', 'chahrazad', 'chahrazed', 'chaima', 'chaimaa', 'chaimae', 'chaina', 'chainez', 'chaineze', 'chakib', 'chakir', 'chams', 'chamseddine', 'chana', 'chanel', 'chanelle', 'chanez', 'chantal', 'chantale', 'chaouki', 'charif', 'charlaine', 'charleen', 'charlelie', 'charlemagne', 'charlene', 'charles', 'charles-alexandre', 'charles-andre', 'charles-antoine', 'charles-edouard', 'charles-elie', 'charles-emmanuel', 'charles-henri', 'charles-henry', 'charlesia', 'charlette', 'charley', 'charli', 'charlie', 'charline', 'charlise', 'charlize', 'charlot', 'charlotte', 'charly', 'charlyne', 'charlene', 'chayma', 'chaymaa', 'chaymae', 'chaima', 'cheick', 'cheikh', 'cheima', 'chelsea', 'chelsy', 'chems', 'chems-eddine', 'chemseddine', 'cherazade', 'cherif', 'cherifa', 'cherine', 'cheryl', 'cheryne', 'cheyenne', 'cheyma', 'chiara', 'chimene', 'chiraz', 'chirine', 'chjara', 'chlea', 'chloe', 'chloee', 'chloe', 'chloe', 'chlea', 'chokri', 'chouaib', 'choukri', 'chretien', 'chris', 'chrislaine', 'christ', 'christa', 'christal', 'christel', 'christelle', 'christian', 'christiana', 'christiane', 'christianne', 'christiano', 'christie', 'christina', 'christine', 'christofer', 'christophe', 'christopher', 'christy', 'christele', 'chrys', 'chrystal', 'chrystel', 'chrystele', 'chrystelle', 'chrystele', 'cherine', 'ciana', 'ciara', 'cidalia', 'cigdem', 'cihan', 'cilia', 'cindie', 'cindy', 'cinthia', 'cinthya', 'circe', 'cisse', 'cladie', 'clair', 'claire', 'claire-lise', 'claire-marie', 'clairette', 'clara', 'clarence', 'clarice', 'clarissa', 'clarisse', 'clarys', 'clarysse', 'claude', 'claudette', 'claudia', 'claudie', 'claudine', 'claudio', 'claudius', 'claudy', 'clayton', 'clea', 'clelia', 'clelie', 'clemence', 'clement', 'clementine', 'cleo', 'cleophee', 'clervie', 'clet', 'cliff', 'clio', 'clodomir', 'cloe', 'clorinde', 'clotaire', 'clothilde', 'clotilde', 'clovis', 'cloe', 'clyde', 'clea', 'clelia', 'clelie', 'clemence', 'clement', 'clementine', 'cleo', 'cleophee', 'cody', 'colas', 'colbert', 'coleen', 'colette', 'colin', 'coline', 'colleen', 'collette', 'colline', 'collyne', 'colombe', 'colombine', 'colyne', 'come', 'concepcion', 'conception', 'concetta', 'conchita', 'conrad', 'constance', 'constantin', 'constantine', 'consuelo', 'cora', 'coralie', 'coraline', 'coraly', 'coralyne', 'corantin', 'corenthin', 'corentin', 'corentine', 'corine', 'corinne', 'corneille', 'cornelia', 'cornelie', 'corrine', 'corto', 'cory', 'cosette', 'cosimo', 'cosme', 'coumba', 'crepin', 'crescent', 'cristal', 'cristel', 'cristelle', 'cristian', 'cristiano', 'cristina', 'cristine', 'cristobal', 'crystal', 'crystale', 'crystel', 'crystelle', 'curt', 'curtis', 'cyana', 'cyane', 'cyann', 'cybelia', 'cylia', 'cylian', 'cyndel', 'cyndelle', 'cyndi', 'cyndia', 'cyndie', 'cynthia', 'cyntia', 'cyprien', 'cyprienne', 'cyr', 'cyriac', 'cyrian', 'cyriane', 'cyriaque', 'cyriel', 'cyrielle', 'cyril', 'cyrill', 'cyrille', 'cyrine', 'cyrus', 'czeslaw', 'czeslawa', 'cecile', 'cecilia', 'cedric', 'cedrick', 'celeste', 'celestin', 'celestine', 'celia', 'celian', 'celie', 'celina', 'celine', 'celya', 'celyan', 'celena', 'cesar', 'come', 'dado', 'dahbia', 'dahlia', 'daina', 'daisy', 'dalia', 'dalida', 'dalil', 'dalila', 'dalla', 'dalya', 'damaris', 'damian', 'damien', 'damienne', 'damiens', 'damla', 'damon', 'dan', 'dana', 'danae', 'danae', 'dani', 'dania', 'danie', 'daniel', 'daniela', 'daniele', 'daniella', 'danielle', 'danila', 'danilo', 'daniele', 'dann', 'danny', 'dante', 'danton', 'dany', 'danya', 'danyl', 'daoud', 'daouda', 'daphne', 'daphnee', 'daphne', 'daphnee', 'dara', 'darell', 'daren', 'daria', 'darina', 'darine', 'dario', 'daris', 'darius', 'darko', 'darlene', 'darren', 'darryl', 'daryl', 'dastan', 'dave', 'david', 'david-alexandre', 'davide', 'davina', 'davis', 'davy', 'dawson', 'dayan', 'dayana', 'dayane', 'dayann', 'dayna', 'dayron', 'dayvon', 'dean', 'debora', 'deborah', 'debra', 'declan', 'defne', 'dejan', 'delhia', 'delia', 'delinda', 'delphin', 'delphine', 'delya', 'demba', 'denia', 'denis', 'denisa', 'denise', 'deniz', 'denize', 'dennis', 'denovan', 'denys', 'denyse', 'denzel', 'derek', 'derya', 'desir', 'desiree', 'destiny', 'deva', 'deven', 'devon', 'devran', 'devy', 'dewi', 'deyan', 'diaba', 'diadie', 'diana', 'diane', 'diarra', 'didier', 'diego', 'dienaba', 'dieneba', 'dieudonne', 'dieynaba', 'dikra', 'dila', 'dilan', 'dilara', 'dilek', 'dilhan', 'dimitri', 'dimitry', 'dina', 'dinah', 'dinis', 'dino', 'diogo', 'divine', 'diyar', 'diego', 'djalil', 'djamal', 'djamel', 'djamil', 'djamila', 'djamilla', 'django', 'djason', 'djawad', 'djayan', 'djebril', 'djelloul', 'djemal', 'djemel', 'djemila', 'djena', 'djenaba', 'djeneba', 'djenna', 'djessim', 'djessy', 'djibril', 'djiby', 'djilali', 'djillali', 'djimmy', 'djina', 'djino', 'djulian', 'dogan', 'doha', 'dolly', 'dolores', 'dolores', 'domenica', 'domenico', 'domingo', 'domingos', 'dominic', 'dominica', 'dominique', 'domitille', 'don', 'dona', 'donald', 'donat', 'donatella', 'donatien', 'donatienne', 'donato', 'donavan', 'donia', 'donna', 'donovan', 'donya', 'dora', 'dorcas', 'doreen', 'doria', 'dorian', 'doriana', 'doriane', 'doriann', 'dorianne', 'dorina', 'dorine', 'doris', 'dorothee', 'dorothy', 'dorothee', 'dorra', 'dorsaf', 'doryan', 'doua', 'douaa', 'douglas', 'dounia', 'dounya', 'dov', 'dragan', 'dragana', 'dramane', 'driss', 'duarte', 'duncan', 'dune', 'duygu', 'dwayne', 'dyclan', 'dylan', 'dylane', 'dylann', 'dyna', 'debora', 'deborah', 'delia', 'desire', 'desiree', 'ebru', 'ecrin', 'eda', 'edan', 'edanur', 'eddie', 'eddine', 'eddy', 'edeline', 'edem', 'eden', 'edene', 'edenn', 'edern', 'edgar', 'edgard', 'edin', 'edith', 'edithe', 'ediz', 'edme', 'edmee', 'edmond', 'edmonde', 'edna', 'edouard', 'edouardo', 'edson', 'eduard', 'eduardo', 'edvard', 'edvin', 'edward', 'edwige', 'edwin', 'edwina', 'edy', 'edene', 'efe', 'efflam', 'eglantine', 'egon', 'eileen', 'eitan', 'ekrem', 'ela', 'elaia', 'elaine', 'elana', 'elanur', 'elaura', 'elaia', 'elda', 'elea', 'eleana', 'eleane', 'eleanor', 'eleanore', 'elen', 'elena', 'eleonor', 'eleonora', 'eleonore', 'elfie', 'elfriede', 'elfy', 'elhadj', 'elhadji', 'elham', 'eli', 'elia', 'eliakim', 'eliam', 'elian', 'eliana', 'eliane', 'elianne', 'elias', 'eliaz', 'elicia', 'elida', 'elidjah', 'elie', 'eliel', 'elien', 'elies', 'eliette', 'eliezer', 'elif', 'elijah', 'elikya', 'elin', 'elina', 'eline', 'elinor', 'elio', 'elior', 'eliora', 'eliot', 'elioth', 'eliott', 'elisa', 'elisabete', 'elisabeth', 'elise', 'elisee', 'elisha', 'elissa', 'eliya', 'eliz', 'eliza', 'elizabete', 'elizabeth', 'elizio', 'ella', 'ellen', 'ellia', 'ellie', 'elliot', 'elliott', 'elly', 'ellyn', 'ellyne', 'elma', 'elmire', 'eloa', 'eloan', 'eloane', 'eloann', 'elodie', 'elody', 'elohim', 'eloi', 'eloine', 'elois', 'eloise', 'elona', 'elora', 'elorri', 'elouan', 'elouane', 'elouann', 'elouen', 'elowan', 'eloy', 'eloise', 'elric', 'elsa', 'else', 'elsie', 'elsy', 'elvan', 'elvin', 'elvina', 'elvira', 'elvire', 'elvis', 'elwan', 'elwenn', 'ely', 'elya', 'elyah', 'elyan', 'elyana', 'elyane', 'elyas', 'elyass', 'elyes', 'elyess', 'elyette', 'elyn', 'elyna', 'elyne', 'elynn', 'elyo', 'elyot', 'elyott', 'elysa', 'elyse', 'elysee', 'elyssa', 'elza', 'elea', 'eleana', 'eleanor', 'eleanore', 'elena', 'eleonore', 'ema', 'emanuel', 'emanuela', 'emanuelle', 'emel', 'emelia', 'emelie', 'emeline', 'emelyne', 'emerance', 'emeraude', 'emeric', 'emerick', 'emerik', 'emerson', 'emery', 'emi', 'emie', 'emil', 'emile', 'emilia', 'emiliano', 'emilie', 'emilien', 'emilienne', 'emilio', 'emily', 'emin', 'emina', 'emine', 'emir', 'emira', 'emirhan', 'emma', 'emmanuel', 'emmanuela', 'emmanuele', 'emmanuella', 'emmanuelle', 'emmeline', 'emmie', 'emmy', 'emna', 'emrah', 'emre', 'emrick', 'emrys', 'emy', 'ena', 'enael', 'enael', 'enaelle', 'encarnacion', 'endy', 'enea', 'eneko', 'enes', 'engin', 'enguerran', 'enguerrand', 'enis', 'enki', 'ennio', 'enoa', 'enogat', 'enoha', 'enola', 'enora', 'enorah', 'enric', 'enrick', 'enrico', 'enrique', 'ensar', 'enya', 'enza', 'enzo', 'enea', 'eole', 'eolia', 'ephraim', 'ephrem', 'epiphane', 'epiphanie', 'eponine', 'eray', 'ercan', 'erdem', 'erell', 'eren', 'erhan', 'eric', 'erica', 'erich', 'erick', 'ericka', 'erik', 'erika', 'erin', 'erina', 'erine', 'erkan', 'erna', 'ernest', 'ernestine', 'ernesto', 'erol', 'eros', 'ersin', 'erva', 'ervin', 'erwan', 'erwann', 'erwin', 'eryn', 'eryne', 'erynn', 'esaie', 'esila', 'esin', 'eslem', 'esma', 'esmanur', 'esmeralda', 'esmee', 'esperance', 'esperanza', 'esra', 'essia', 'esteban', 'estebane', 'estebann', 'estel', 'estella', 'estelle', 'ester', 'estevan', 'esteve', 'esther', 'estrella', 'esteban', 'etan', 'etann', 'ethan', 'ethane', 'ethann', 'ethel', 'etienne', 'etiennette', 'etiennise', 'eudes', 'eudoxie', 'eugenia', 'eugenie', 'eugenio', 'eugene', 'eugenie', 'eulalie', 'euloge', 'eunice', 'euphemie', 'euphrasie', 'eurydice', 'eusebe', 'eusebio', 'eustache', 'eustase', 'eva', 'evaelle', 'evan', 'evana', 'evane', 'evangeline', 'evann', 'evans', 'evariste', 'eve', 'eve-marie', 'evelina', 'eveline', 'evelyn', 'evelyne', 'evelyse', 'even', 'evenor', 'evens', 'evie', 'evin', 'evodie', 'evrard', 'evy', 'ewa', 'ewald', 'ewan', 'ewann', 'ewen', 'ewenn', 'expedit', 'expedite', 'eya', 'eyal', 'eyden', 'eylem', 'eymen', 'eymeric', 'eytan', 'eythan', 'eyup', 'ezechiel', 'ezekiel', 'ezel', 'ezequiel', 'ezgi', 'ezilda', 'ezio', 'ezra', 'ezzio', 'ezechiel', 'fabian', 'fabien', 'fabienne', 'fabio', 'fabiola', 'fabrice', 'fabrizio', 'fadel', 'fadela', 'fadi', 'fadia', 'fadil', 'fadila', 'fadime', 'fadoua', 'fadwa', 'fady', 'fael', 'fahad', 'fahd', 'fahed', 'fahim', 'fahima', 'faical', 'fairouz', 'faisal', 'faissal', 'faith', 'faiz', 'faiza', 'fallon', 'fallone', 'falone', 'fanch', 'fanchon', 'fanelie', 'fanette', 'fanie', 'fannie', 'fanny', 'fanta', 'fantin', 'fantine', 'fany', 'faouzi', 'faouzia', 'farah', 'farel', 'farell', 'fares', 'farha', 'farid', 'farida', 'faride', 'faris', 'farouk', 'farrah', 'fares', 'fatah', 'faten', 'fathi', 'fathia', 'fatia', 'fatih', 'fatiha', 'fatim', 'fatima', 'fatima-zahra', 'fatima-zohra', 'fatimata', 'fatine', 'fatma', 'fatna', 'fatou', 'fatouma', 'fatoumata', 'faty', 'faustin', 'faustine', 'fauve', 'fawzi', 'faycal', 'faycel', 'fayrouz', 'faysal', 'fayssal', 'fayza', 'faycal', 'fazia', 'faiza', 'federico', 'felice', 'felicia', 'felicie', 'felicien', 'felicienne', 'felicite', 'felipe', 'felix', 'fella', 'fenda', 'ferdi', 'ferdinand', 'ferdinande', 'ferhat', 'feriel', 'fernand', 'fernanda', 'fernande', 'fernando', 'ferreol', 'feryel', 'fethi', 'feyza', 'fidele', 'fideline', 'fidji', 'filip', 'filipe', 'filippo', 'filiz', 'filomena', 'fily', 'fiona', 'fiorella', 'firas', 'firat', 'firdaous', 'firdaws', 'firmin', 'firmine', 'flavia', 'flavian', 'flavie', 'flavien', 'flavienne', 'flavio', 'flavy', 'fleurine', 'fleury', 'flora', 'floran', 'florane', 'flore', 'floreal', 'florelle', 'florence', 'florent', 'florentin', 'florentine', 'florestan', 'florestine', 'florette', 'floria', 'florian', 'floriana', 'floriane', 'florianne', 'floriant', 'florida', 'florie', 'florient', 'florimond', 'florin', 'florina', 'florinda', 'florine', 'floris', 'florise', 'floryan', 'fode', 'fodie', 'fortuna', 'fortunee', 'fouad', 'foucauld', 'foued', 'foune', 'fouzi', 'fouzia', 'franc', 'franca', 'france-lise', 'franceline', 'francelise', 'francesca', 'francesco', 'francette', 'francia', 'franciane', 'francine', 'francis', 'francisca', 'francisco', 'francise', 'francisque', 'franck', 'franckie', 'francky', 'franco', 'francois', 'frank', 'frankie', 'franklin', 'franky', 'frantz', 'franz', 'francois', 'francois-joseph', 'francois-marie', 'francois-regis', 'francois-xavier', 'francoise', 'fred', 'freddy', 'frederick', 'frederico', 'frederik', 'fredy', 'frida', 'fridolin', 'frieda', 'fritz', 'frederic', 'frederick', 'frederique', 'fulbert', 'funda', 'furkan', 'felicia', 'felicie', 'felicien', 'felix', 'feriel', 'gabi', 'gabie', 'gabin', 'gabriel', 'gabriela', 'gabriele', 'gabriella', 'gabrielle', 'gabryel', 'gaby', 'gad', 'gael', 'gaele', 'gaelle', 'gaetan', 'gaetane', 'gaetano', 'gaia', 'galaad', 'gamze', 'gaoussou', 'garance', 'garry', 'gary', 'gaspar', 'gaspard', 'gaston', 'gatien', 'gatienne', 'gaultier', 'gauthier', 'gautier', 'gauvain', 'gavin', 'gaya', 'gaye', 'gaylor', 'gaylord', 'gaetan', 'gael', 'gaelle', 'gaetan', 'gaetane', 'gaia', 'gebril', 'gedeon', 'gemma', 'gena', 'genevieve', 'genna', 'gennaro', 'gentil', 'geoffray', 'geoffrey', 'geoffroy', 'george', 'georges', 'georges-marie', 'georget', 'georgette', 'georgia', 'georgina', 'georgine', 'geraldine', 'gerardine', 'geraud', 'gerda', 'geremy', 'germain', 'germaine', 'germinal', 'gerome', 'gersende', 'gertrude', 'gerty', 'gervais', 'gervaise', 'gery', 'ghania', 'ghislain', 'ghislaine', 'ghizlane', 'ghjulia', 'ghyslain', 'ghyslaine', 'giacomo', 'gian', 'giani', 'gianna', 'gianni', 'gianny', 'gibril', 'gil', 'gilbert', 'gilberte', 'gilberto', 'gilda', 'gildas', 'gilette', 'giliane', 'gille', 'gilles', 'gillette', 'gillian', 'gilliane', 'gina', 'gines', 'ginette', 'ginger', 'gino', 'gioia', 'giorgia', 'giorgio', 'giovani', 'giovanna', 'giovanni', 'giovanny', 'giovany', 'gipsy', 'girard', 'giselaine', 'giselle', 'gishlaine', 'gislain', 'gislaine', 'gislene', 'gislhaine', 'gismonde', 'gisele', 'giulia', 'giulian', 'giuliana', 'giuliano', 'giulio', 'giuseppe', 'giuseppina', 'gizem', 'gladys', 'glawdys', 'glen', 'glenn', 'gloire', 'gloria', 'glwadys', 'godefroy', 'godeleine', 'godfroy', 'gokhan', 'gontran', 'gontrand', 'gonzague', 'goran', 'gordana', 'gordon', 'goulven', 'goulwen', 'goundo', 'goundoba', 'gracia', 'gracianne', 'gracie', 'gratianne', 'gratien', 'gratienne', 'grazia', 'graziella', 'greg', 'gregoire', 'gregor', 'gregori', 'gregorio', 'gregory', 'greta', 'gregoire', 'gregory', 'gualbert', 'guenael', 'guenaelle', 'guenhael', 'guenola', 'guenole', 'guerric', 'guewen', 'gui', 'guido', 'guilain', 'guilaine', 'guilene', 'guilhem', 'guilherme', 'guilian', 'guillaume', 'guillaumette', 'guillaumine', 'guillem', 'guillemette', 'guillermo', 'guillian', 'guirec', 'guiseppe', 'guiseppina', 'guislain', 'guislaine', 'gul', 'gulay', 'gulcan', 'gunther', 'gurvan', 'gurwan', 'gustave', 'gustavie', 'gustavo', 'guy', 'guylain', 'guylaine', 'guylene', 'guylene', 'gweltaz', 'gwen', 'gwenael', 'gwenaele', 'gwenaelle', 'gwenael', 'gwenaelle', 'gwendal', 'gwendolina', 'gwendoline', 'gwendolyn', 'gwendolyne', 'gwenegan', 'gwenn', 'gwennael', 'gwennaelle', 'gwennaelle', 'gwenola', 'gwenole', 'gwenvael', 'gwladys', 'gwenael', 'gwenaelle', 'gwenola', 'gysele', 'gyslaine', 'gerald', 'geraldine', 'gerard', 'geraud', 'habib', 'habiba', 'habibatou', 'haby', 'hacen', 'hacene', 'hacer', 'hachim', 'haci', 'hacina', 'hada', 'hadassa', 'hadda', 'hadi', 'hadia', 'hadidja', 'hadil', 'hadj', 'hadja', 'hadjar', 'hadjer', 'hadjira', 'hadrien', 'hafid', 'hafida', 'hafsa', 'hafssa', 'hager', 'haifa', 'haikel', 'hailey', 'hajar', 'hajare', 'hajer', 'hakan', 'hakim', 'hakima', 'hala', 'haley', 'halil', 'halim', 'halima', 'halimatou', 'halime', 'halina', 'hamadi', 'hamady', 'hamdi', 'hamed', 'hamel', 'hamid', 'hamida', 'hamidou', 'hamza', 'hana', 'hanaa', 'hanae', 'hanan', 'hanane', 'hanae', 'hanae', 'handy', 'hanen', 'hanene', 'hani', 'hania', 'hanifa', 'hanine', 'hanna', 'hannah', 'hannelore', 'hans', 'hanya', 'harald', 'haris', 'harmonie', 'harmony', 'harold', 'haron', 'harone', 'haroun', 'harouna', 'haroune', 'harris', 'harrison', 'harry', 'harun', 'hasan', 'hasna', 'hassan', 'hassane', 'hassen', 'hassiba', 'hassina', 'hassna', 'hatem', 'hatice', 'hatim', 'hatouma', 'hatoumata', 'haude', 'hava', 'havin', 'havva', 'hawa', 'haya', 'hayat', 'hayate', 'haydan', 'hayden', 'hayet', 'hayette', 'haykel', 'hayley', 'haytam', 'haytem', 'haytham', 'haythem', 'hazal', 'hazel', 'heather', 'heaven', 'hector', 'heddy', 'hedi', 'hedia', 'hedwig', 'hedwige', 'hedy', 'heidi', 'heinz', 'hela', 'helder', 'helea', 'helen', 'helena', 'helene', 'helga', 'helia', 'heliane', 'helie', 'helier', 'heliette', 'helin', 'heline', 'helio', 'helios', 'hella', 'helmut', 'helmuth', 'heloise', 'helyett', 'helyette', 'henda', 'hendrick', 'henri', 'henri-claude', 'henri-pierre', 'henria', 'henrick', 'henriette', 'henrik', 'henrique', 'henry', 'henryk', 'henzo', 'herbert', 'herman', 'hermance', 'hermann', 'hermes', 'hermine', 'herminie', 'hermione', 'herveline', 'herve', 'heyden', 'hiba', 'hicham', 'hichame', 'hichem', 'hidaya', 'hilaire', 'hilal', 'hilarion', 'hilary', 'hilda', 'hilde', 'hildegard', 'hildegarde', 'hildevert', 'hilel', 'hillary', 'hillel', 'hina', 'hinata', 'hinatea', 'hind', 'hinda', 'hinde', 'hippolyte', 'hira', 'hiranur', 'hoang', 'hoche', 'hocine', 'hoda', 'hoel', 'homere', 'honorat', 'honore', 'honoree', 'honorine', 'honore', 'hope', 'horace', 'horacio', 'horia', 'horst', 'hortense', 'hortensia', 'hosni', 'houari', 'houcine', 'houda', 'houleye', 'houria', 'houssam', 'houssem', 'houssine', 'hubert', 'huberte', 'hubertine', 'hugo', 'hugues', 'huguette', 'hulya', 'humbert', 'humberto', 'huseyin', 'hussein', 'hyacinthe', 'hylan', 'hyppolite', 'hedi', 'helia', 'helio', 'helios', 'heloise', 'helena', 'helene', 'helena', 'ian', 'ianis', 'iannis', 'iban', 'ibrahim', 'ibrahima', 'ibtissam', 'ibtissame', 'ibtissem', 'icham', 'ichem', 'ida', 'idalina', 'idir', 'idoia', 'idris', 'idriss', 'idrissa', 'ignace', 'ignacio', 'igor', 'ihab', 'iheb', 'ihsan', 'ihsane', 'ihssane', 'ikram', 'ikrame', 'ilan', 'ilana', 'ilane', 'ilann', 'ilario', 'ilayda', 'ilda', 'ildevert', 'ileana', 'ilef', 'ilena', 'ilham', 'ilhame', 'ilhan', 'ilhem', 'ilian', 'iliana', 'iliane', 'ilias', 'ilies', 'ilina', 'ilies', 'ilker', 'ilknur', 'illan', 'illana', 'illian', 'illiana', 'illies', 'illona', 'illyana', 'illyes', 'ilona', 'ilse', 'ilyam', 'ilyan', 'ilyana', 'ilyane', 'ilyann', 'ilyanna', 'ilyas', 'ilyass', 'ilyasse', 'ilyes', 'ilyess', 'ilyesse', 'ilyes', 'ileana', 'ilena', 'imad', 'imade', 'iman', 'imane', 'imani', 'imanol', 'imany', 'imed', 'imelda', 'imen', 'imene', 'imran', 'imrane', 'imran', 'imene', 'ina', 'inaki', 'inas', 'inaya', 'inayah', 'inaia', 'incarnation', 'india', 'indiana', 'indira', 'indra', 'indy', 'inel', 'ines', 'iness', 'inesse', 'ingrid', 'inna', 'innaya', 'insaf', 'inssaf', 'intissar', 'ines', 'ines', 'ines', 'ioan', 'ioana', 'iona', 'ipek', 'irem', 'irena', 'irenee', 'irfan', 'irina', 'iris', 'irma', 'irmgard', 'irmine', 'irvin', 'irwin', 'irys', 'irene', 'isa', 'isaac', 'isaak', 'isabel', 'isabella', 'isabelle', 'isac', 'isadora', 'isaia', 'isaiah', 'isaie', 'isak', 'isaline', 'isalyne', 'isalys', 'isam', 'isao', 'isaura', 'isaure', 'isaiah', 'iseult', 'ishak', 'ishaq', 'isia', 'isidore', 'isis', 'islam', 'islem', 'isleym', 'isma', 'ismael', 'ismahan', 'ismahane', 'ismail', 'ismaila', 'ismael', 'ismail', 'ismerie', 'isoline', 'isra', 'israa', 'israe', 'israel', 'issa', 'issam', 'issra', 'italo', 'ivan', 'ivana', 'ivane', 'ivann', 'ivanna', 'ivette', 'ivo', 'ivonne', 'ivy', 'iwan', 'iwen', 'iyad', 'iyed', 'izak', 'izia', 'izzie', 'izia', 'jacinthe', 'jack', 'jacki', 'jackie', 'jackson', 'jacky', 'jacob', 'jacquelin', 'jacqueline', 'jacques', 'jacques-olivier', 'jacqui', 'jacquie', 'jacquy', 'jad', 'jade', 'jaden', 'jadwiga', 'jael', 'jahid', 'jahyan', 'jahyann', 'jakie', 'jaky', 'jalal', 'jalane', 'jalil', 'jalila', 'jalis', 'jamal', 'jamel', 'james', 'jamie', 'jamil', 'jamila', 'jamy', 'jan', 'jana', 'jane', 'janel', 'janelle', 'janet', 'janette', 'janice', 'janick', 'janie', 'janik', 'janina', 'janine', 'janique', 'janis', 'janna', 'jannah', 'jannat', 'jannick', 'jannie', 'jannine', 'janny', 'jany', 'janyce', 'jaouad', 'jaoued', 'jaouen', 'jared', 'jarod', 'jasmin', 'jasmina', 'jasmine', 'jason', 'jassem', 'jassim', 'jauffrey', 'javier', 'jawad', 'jawed', 'jay', 'jaya', 'jayan', 'jayden', 'jayson', 'jean', 'jean-alain', 'jean-albert', 'jean-alexandre', 'jean-andre', 'jean-antoine', 'jean-baptiste', 'jean-benoit', 'jean-bernard', 'jean-brice', 'jean-bruno', 'jean-camille', 'jean-charles', 'jean-christian', 'jean-christophe', 'jean-claude', 'jean-damien', 'jean-daniel', 'jean-david', 'jean-denis', 'jean-didier', 'jean-dominique', 'jean-edouard', 'jean-elie', 'jean-emile', 'jean-emmanuel', 'jean-eric', 'jean-etienne', 'jean-eudes', 'jean-fabrice', 'jean-francis', 'jean-francois', 'jean-fred', 'jean-frederic', 'jean-felix', 'jean-gabriel', 'jean-georges', 'jean-gilles', 'jean-guillaume', 'jean-guy', 'jean-gerard', 'jean-henri', 'jean-herve', 'jean-hubert', 'jean-hugues', 'jean-jack', 'jean-jacques', 'jean-joseph', 'jean-jose', 'jean-joel', 'jean-julien', 'jean-laurent', 'jean-lou', 'jean-louis', 'jean-loup', 'jean-loic', 'jean-luc', 'jean-lucien', 'jean-manuel', 'jean-marc', 'jean-marcel', 'jean-marie', 'jean-mary', 'jean-mathieu', 'jean-matthieu', 'jean-maurice', 'jean-max', 'jean-maxime', 'jean-michel', 'jean-nicolas', 'jean-noel', 'jean-olivier', 'jean-pascal', 'jean-patrice', 'jean-patrick', 'jean-paul', 'jean-philippe', 'jean-pierre', 'jean-pol', 'jean-raphael', 'jean-raymond', 'jean-rene', 'jean-richard', 'jean-robert', 'jean-roch', 'jean-roger', 'jean-romain', 'jean-remi', 'jean-remy', 'jean-stephane', 'jean-sebastien', 'jean-thierry', 'jean-thomas', 'jean-victor', 'jean-vincent', 'jean-yann', 'jean-yves', 'jeane', 'jeanette', 'jeanick', 'jeanine', 'jeaninne', 'jeanne', 'jeanne-marie', 'jeannette', 'jeannick', 'jeannie', 'jeannina', 'jeannine', 'jeannot', 'jeanny', 'jebril', 'jed', 'jeff', 'jefferson', 'jeffrey', 'jehan', 'jehane', 'jehanne', 'jelena', 'jemima', 'jena', 'jenifer', 'jenna', 'jennah', 'jennie', 'jennifer', 'jenny', 'jennyfer', 'jeoffrey', 'jeremi', 'jeremie', 'jeremy', 'jerome', 'jeromine', 'jerry', 'jersey', 'jerome', 'jeson', 'jess', 'jesse', 'jessica', 'jessie', 'jessika', 'jessim', 'jessy', 'jessyca', 'jessym', 'jesus', 'jeyson', 'jezabel', 'jhonny', 'jibril', 'jihad', 'jihan', 'jihane', 'jihed', 'jihene', 'jill', 'jillian', 'jim', 'jimi', 'jimmy', 'jimy', 'jinane', 'jiyan', 'jo', 'joachim', 'joachin', 'joackim', 'joakim', 'joan', 'joana', 'joane', 'joanes', 'joanie', 'joann', 'joanna', 'joanne', 'joannes', 'joannie', 'joanny', 'joany', 'joao', 'joaquim', 'joaquin', 'joaquina', 'jocelin', 'joceline', 'jocelyn', 'jocelyne', 'jocya', 'jodie', 'jody', 'joe', 'joel', 'joele', 'joevin', 'joey', 'joffray', 'joffre', 'joffrette', 'joffrey', 'johan', 'johana', 'johane', 'johann', 'johanna', 'johanne', 'johannes', 'johannie', 'johanny', 'john', 'johnatan', 'johnathan', 'johnny', 'johny', 'jolan', 'jon', 'jonah', 'jonas', 'jonatan', 'jonathan', 'jonathann', 'jonny', 'joran', 'jordan', 'jordane', 'jordann', 'jordi', 'jordy', 'jorge', 'jorick', 'joris', 'jorys', 'joscelyne', 'josee', 'josef', 'josefa', 'joseline', 'joselito', 'joselyne', 'joseph', 'josepha', 'josephe', 'josephine', 'josephte', 'josette', 'josh', 'joshua', 'josian', 'josiane', 'josianne', 'josias', 'josie', 'joss', 'josse', 'josselin', 'josseline', 'josselyn', 'josselyne', 'jossua', 'josua', 'josue', 'josue', 'josy', 'josyane', 'jose', 'jose-antonio', 'jose-luis', 'jose-manuel', 'jose-maria', 'jose-marie', 'josee', 'josephine', 'joud', 'joudia', 'joulia', 'joumana', 'jounayd', 'jovan', 'jovanny', 'jovany', 'joy', 'joyce', 'joye', 'joe', 'joel', 'joelle', 'juan', 'juan-carlos', 'juana', 'juanita', 'juanito', 'juba', 'jude', 'judes', 'judicael', 'judicaelle', 'judicael', 'judikael', 'judith', 'judy', 'jugurtha', 'jule', 'julen', 'jules', 'julia', 'julian', 'juliana', 'juliane', 'juliann', 'julianna', 'julianne', 'juliano', 'julie', 'julie-anne', 'julien', 'julienne', 'juliet', 'juliette', 'juline', 'julio', 'julius', 'jullian', 'julot', 'july', 'julya', 'julyan', 'jun', 'junayd', 'june', 'junior', 'jurgen', 'just', 'juste', 'justin', 'justina', 'justine', 'justinien', 'jerome', 'jeremie', 'jeremy', 'jerome', 'kaan', 'kacem', 'kaci', 'kacy', 'kaddour', 'kader', 'kadia', 'kadiatou', 'kadidia', 'kadidiatou', 'kadidja', 'kadija', 'kadir', 'kady', 'kael', 'kaelig', 'kaena', 'kahil', 'kahina', 'kahyna', 'kahys', 'kaila', 'kaina', 'kais', 'kaiss', 'kaissy', 'kaled', 'kali', 'kalid', 'kalidou', 'kalie', 'kalifa', 'kalil', 'kalilou', 'kalista', 'kally', 'kaltoum', 'kalvin', 'kalvyn', 'kaly', 'kalya', 'kalyssa', 'kamal', 'kamel', 'kamelia', 'kamelya', 'kameron', 'kamil', 'kamila', 'kamilia', 'kamille', 'kamilya', 'kamron', 'kamelia', 'kani', 'kany', 'kaoutar', 'kaouthar', 'kara', 'karam', 'karamba', 'kardiatou', 'kareen', 'karel', 'karell', 'karelle', 'karen', 'karene', 'karim', 'karima', 'karime', 'karin', 'karina', 'karine', 'karinne', 'karl', 'karla', 'karol', 'karolina', 'karyne', 'kassandra', 'kassandre', 'kassidy', 'kassie', 'kassim', 'kassy', 'kataleya', 'katalina', 'katarina', 'kate', 'katel', 'kateline', 'katell', 'katharina', 'katherine', 'kathia', 'kathleen', 'kathy', 'katia', 'katiana', 'katie', 'katleen', 'katty', 'katy', 'katya', 'kawtar', 'kawthar', 'kaya', 'kayden', 'kayla', 'kaylan', 'kaylee', 'kaylia', 'kayliah', 'kaylie', 'kayline', 'kayna', 'kayron', 'kays', 'kayss', 'kael', 'kaila', 'kaily', 'kaina', 'kais', 'kaiss', 'keenan', 'keila', 'keira', 'keissy', 'kelia', 'kelian', 'keliane', 'kelig', 'kellia', 'kellian', 'kellie', 'kelly', 'kellya', 'kellyan', 'kelsy', 'keltoum', 'kelvin', 'kelvyn', 'kelya', 'kelyah', 'kelyan', 'kelyane', 'kelyann', 'kelyssa', 'kemal', 'kemil', 'ken', 'kenan', 'kendall', 'kendji', 'kendjy', 'kendra', 'kendrick', 'kendy', 'kenji', 'kenjy', 'kenneth', 'kenny', 'kentin', 'keny', 'kenya', 'kenza', 'kenzi', 'kenzo', 'kenzy', 'keo', 'keran', 'kerem', 'keren', 'kerian', 'kerim', 'kerrian', 'kerry', 'kerwan', 'keryan', 'keryann', 'kesia', 'kessie', 'kessy', 'ketsia', 'ketty', 'kevan', 'keven', 'kevin', 'kevser', 'kevyn', 'kewan', 'kewin', 'keyan', 'keyla', 'keylan', 'keylia', 'keyliah', 'keylian', 'keyna', 'keyran', 'keyron', 'keysha', 'keyvan', 'kezia', 'keziah', 'khadidiatou', 'khadidja', 'khadija', 'khadim', 'khadra', 'khady', 'khaled', 'khalid', 'khalida', 'khalifa', 'khalil', 'khalis', 'khalissa', 'khedidja', 'kheira', 'khira', 'khloe', 'kian', 'kiana', 'kiara', 'kiera', 'kieran', 'kilian', 'kiliane', 'kiliann', 'killian', 'killyan', 'kilyan', 'kilyann', 'kim', 'kimany', 'kimberlay', 'kimberley', 'kimberly', 'kimi', 'kimia', 'kimy', 'kimya', 'kinan', 'kingsley', 'kinsley', 'kira', 'kiran', 'kirsten', 'kiyan', 'kiyane', 'klara', 'klea', 'kleber', 'klebert', 'klervi', 'klervie', 'kloe', 'kloe', 'klea', 'koray', 'korentin', 'kouider', 'koumba', 'kris', 'kristel', 'kristell', 'kristelle', 'kristen', 'kristina', 'kristopher', 'kristy', 'krys', 'krystal', 'krystel', 'krystelle', 'kubra', 'kurt', 'kurtis', 'kurtys', 'kyan', 'kyara', 'kylan', 'kyle', 'kylia', 'kylian', 'kyliana', 'kyliane', 'kyliann', 'kylie', 'kyllian', 'kymani', 'kyra', 'kyran', 'kyrian', 'kelia', 'kelian', 'kelio', 'kelya', 'kelyan', 'keo', 'keran', 'kevin', 'keziah', 'ladislas', 'ladji', 'lael', 'laeticia', 'laetitia', 'lahcen', 'lahcene', 'lahna', 'lahouari', 'lahoucine', 'laia', 'laid', 'laila', 'laina', 'lais', 'lakdar', 'lakhdar', 'lala', 'lali', 'lalia', 'lalie', 'lalla', 'lallie', 'lalou', 'laly', 'lalya', 'lambert', 'lamia', 'lamine', 'lamis', 'lamya', 'lana', 'lancelot', 'landry', 'lanna', 'laora', 'lara', 'larbi', 'larissa', 'larry', 'lassana', 'laszlo', 'latifa', 'laura', 'lauralee', 'lauralie', 'lauraline', 'laurana', 'laurane', 'lauranne', 'laure', 'laure-anne', 'laure-helene', 'laureen', 'laureline', 'laurelyne', 'lauren', 'laurena', 'laurence', 'laurencia', 'laurencie', 'laurene', 'laurent', 'laurentine', 'laurette', 'lauriana', 'lauriane', 'laurianne', 'lauric', 'laurie', 'laurie-anne', 'laurina', 'laurinda', 'laurine', 'lauris', 'laury', 'lauryane', 'lauryn', 'lauryne', 'laurene', 'laureline', 'lavinia', 'lawrence', 'laya', 'layan', 'layana', 'layanah', 'layane', 'layann', 'layanna', 'layannah', 'layina', 'layla', 'layna', 'layvin', 'lazar', 'lazare', 'lazarine', 'lazhar', 'laetitia', 'laetitia', 'laia', 'laila', 'laina', 'lea', 'leah', 'leana', 'leandra', 'leandre', 'leandro', 'leane', 'leann', 'leanna', 'leanne', 'lee', 'lee-lou', 'leeloo', 'leelou', 'leena', 'leeroy', 'leger', 'lehna', 'lehyan', 'leia', 'leila', 'leilou', 'leina', 'lelia', 'lelio', 'lemmy', 'lena', 'lenaelle', 'lenaic', 'lenaick', 'lenaig', 'lenaik', 'leni', 'lenna', 'lenni', 'lennie', 'lenny', 'leny', 'lenzo', 'leo', 'leocadie', 'leon', 'leona', 'leonard', 'leonardo', 'leonce', 'leoncia', 'leoncie', 'leonel', 'leonide', 'leonie', 'leonne', 'leonor', 'leonora', 'leonore', 'leonus', 'leony', 'leopold', 'leopoldine', 'lesia', 'leslie', 'lesly', 'leticia', 'letitia', 'letizia', 'letty', 'levana', 'levi', 'levy', 'lewis', 'lexane', 'lexie', 'lexy', 'leya', 'leyan', 'leyana', 'leyla', 'leyna', 'leia', 'leila', 'leina', 'lia', 'liah', 'liam', 'liana', 'liane', 'licia', 'lida', 'lidia', 'lidwine', 'lidy', 'lie', 'lies', 'liham', 'lila', 'lila-rose', 'lilah', 'lilas', 'lilette', 'lili', 'lili-rose', 'lilia', 'lilian', 'liliana', 'liliane', 'lilianne', 'lilie', 'lilio', 'lilirose', 'lilith', 'lilla', 'lilli', 'lillian', 'lilly', 'lilly-rose', 'lilo', 'liloo', 'lilou', 'lilwen', 'lilwenn', 'lily', 'lily-rose', 'lilya', 'lilyan', 'lin', 'lina', 'linaya', 'linda', 'lindsay', 'lindsey', 'lindy', 'line', 'linette', 'lino', 'linoa', 'linsay', 'linsey', 'lio', 'lionel', 'lionelle', 'lionnel', 'lior', 'liora', 'lisa', 'lisa-marie', 'lisandra', 'lisandre', 'lisandro', 'lisandru', 'lisbeth', 'lise', 'lise-marie', 'lisea', 'liselotte', 'lisette', 'lisiane', 'lisie', 'lison', 'lissandre', 'lissandro', 'lisy', 'lisea', 'liv', 'livia', 'livie', 'livio', 'liya', 'liyah', 'liyam', 'liyana', 'liz', 'liza', 'lizea', 'lizie', 'lizon', 'lizy', 'lizzie', 'lizzy', 'lizea', 'lloyd', 'loan', 'loana', 'loane', 'loann', 'loanne', 'lobna', 'loeiz', 'loeiza', 'loelia', 'loetitia', 'loeva', 'loevan', 'logan', 'logane', 'logann', 'loghan', 'lohan', 'lohane', 'lohann', 'loic', 'loicia', 'loick', 'loig', 'loik', 'lois', 'loise', 'lokman', 'lola', 'loli', 'lolie', 'lolita', 'loly', 'lona', 'loni', 'lonny', 'lony', 'loona', 'loqman', 'lora', 'loraine', 'lorane', 'lore', 'lorea', 'loredana', 'loreen', 'loreena', 'lorelei', 'lorelei', 'loreline', 'lorella', 'loren', 'lorena', 'lorene', 'lorenz', 'lorenza', 'lorenzo', 'loretta', 'lorette', 'lori', 'loriana', 'loriane', 'lorianne', 'loric', 'lorick', 'lorie', 'lorik', 'lorin', 'lorina', 'lorine', 'loris', 'lorna', 'lorraine', 'lorrie', 'lorris', 'lorry', 'lory', 'loryne', 'lorys', 'lorene', 'lorena', 'lotfi', 'lothaire', 'lou', 'lou-ann', 'lou-anna', 'lou-anne', 'louan', 'louana', 'louane', 'louann', 'louanne', 'louay', 'loubna', 'louca', 'loucas', 'loucia', 'loucka', 'louen', 'louenn', 'louhane', 'louis', 'louis-alexandre', 'louis-gabriel', 'louis-marie', 'louis-philippe', 'louisa', 'louise', 'louise-marie', 'louisette', 'louisia', 'louisiane', 'louison', 'louiza', 'loujayne', 'louka', 'loukas', 'loula', 'louna', 'lounes', 'lounis', 'lounna', 'lounes', 'loup', 'lourdes', 'loutfi', 'louve', 'lovely', 'lowan', 'lowen', 'loys', 'loe', 'loelia', 'loelie', 'loevan', 'loevan', 'loic', 'loick', 'lois', 'loise', 'luan', 'luana', 'luane', 'lubin', 'luc', 'luca', 'lucas', 'lucay', 'lucca', 'luce', 'lucenzo', 'lucette', 'lucia', 'lucian', 'luciana', 'luciane', 'luciano', 'lucie', 'lucien', 'lucienne', 'lucile', 'lucilia', 'lucille', 'lucinda', 'lucine', 'lucio', 'lucka', 'luckas', 'lucrece', 'lucy', 'lucyle', 'ludger', 'ludivine', 'ludiwine', 'ludmila', 'ludmilla', 'ludovic', 'ludovick', 'ludwig', 'ludyvine', 'lugdivine', 'luidgi', 'luidgy', 'luidji', 'luigi', 'luis', 'luisa', 'luiz', 'luiza', 'luka', 'lukas', 'luke', 'luna', 'lune', 'luqman', 'luther', 'luz', 'ly', 'lya', 'lyah', 'lyam', 'lyana', 'lyanna', 'lycia', 'lyderic', 'lydia', 'lydiane', 'lydie', 'lyes', 'lyess', 'lyha', 'lyham', 'lyhana', 'lyla', 'lylia', 'lylian', 'lyliane', 'lylie', 'lylio', 'lyloo', 'lylou', 'lylwenn', 'lyna', 'lynda', 'lyndsay', 'lyne', 'lynn', 'lynna', 'lyonel', 'lyra', 'lys', 'lysa', 'lysandre', 'lysandro', 'lyse', 'lysea', 'lysia', 'lysiane', 'lysianne', 'lysie', 'lyson', 'lyssandre', 'lyssia', 'lysea', 'lyvan', 'lyvann', 'lyvia', 'lyvio', 'lea', 'lea-marie', 'leah', 'leana', 'leandre', 'leandro', 'leane', 'leanna', 'leanne', 'lelia', 'lelio', 'lena', 'lenaelle', 'lenaic', 'lenais', 'leni', 'leny', 'leo', 'leo-paul', 'leon', 'leona', 'leonard', 'leonce', 'leone', 'leonie', 'leonor', 'leonore', 'leontine', 'leony', 'leopold', 'leopoldine', 'levi', 'levy', 'luna', "m'hamed", 'maamar', 'mabrouk', 'mabrouka', 'maceo', 'macha', 'mackenzie', 'maceo', 'madani', 'maddie', 'maddly', 'maddy', 'madelaine', 'madeleine', 'madeline', 'madelyne', 'maden', 'madenn', 'madi', 'madiana', 'madie', 'madina', 'madison', 'madisson', 'madjid', 'madleen', 'madly', 'mado', 'mady', 'madyson', 'madysson', 'mae', 'mael', 'maela', 'maelan', 'maelane', 'maelann', 'maele', 'maelenn', 'maeli', 'maelia', 'maelie', 'maelig', 'maeline', 'maelis', 'maeliss', 'maelisse', 'maella', 'maelle', 'maellie', 'maelly', 'maellys', 'maelwenn', 'maely', 'maelya', 'maelyne', 'maelys', 'maelyse', 'maelyss', 'maelysse', 'maena', 'maeva', 'maeve', 'maewenn', 'mafalda', 'magali', 'magalie', 'magaly', 'magda', 'magdalena', 'magdelaine', 'magdeleine', 'maggie', 'magguy', 'maggy', 'magid', 'magloire', 'magnolia', 'maguelone', 'maguelonne', 'maguy', 'maha', 'mahamadou', 'mahault', 'mahaut', 'mahawa', 'mahdi', 'mahdy', 'mahe', 'mahee', 'mahel', 'maher', 'mahera', 'maheva', 'mahfoud', 'mahina', 'mahir', 'mahira', 'mahmoud', 'mahmut', 'maho', 'mahe', 'mahee', 'maia', 'maialen', 'maiana', 'maider', 'maika', 'maili', 'mailie', 'mailis', 'mailly', 'maily', 'mailys', 'mailyss', 'maimouna', 'maina', 'maira', 'maissa', 'maissam', 'maissane', 'maite', 'maitena', 'maiwen', 'maiwenn', 'maixent', 'maja', 'majda', 'majdi', 'majdouline', 'majid', 'makan', 'makram', 'maksen', 'maksim', 'malaika', 'malak', 'malaurie', 'malaury', 'malcolm', 'malcom', 'malek', 'malena', 'malia', 'malicia', 'malick', 'malik', 'malika', 'mallaurie', 'mallaury', 'mallorie', 'mallory', 'malo', 'maloe', 'malon', 'malone', 'malonn', 'malorie', 'malory', 'malou', 'maloe', 'malvin', 'malvina', 'malya', 'mama', 'mamadi', 'mamadou', 'mamady', 'mame', 'mamou', 'mamoudou', 'manal', 'manale', 'manar', 'mandy', 'manech', 'manel', 'manele', 'manelle', 'manfred', 'mani', 'manil', 'manny', 'mano', 'manoa', 'manoah', 'manoe', 'manoel', 'manola', 'manolita', 'manolo', 'manon', 'manoe', 'manoe', 'mansour', 'manu', 'manuel', 'manuela', 'manuella', 'manuelle', 'many', 'mao', 'mara', 'maram', 'marc', 'marc-alexandre', 'marc-andre', 'marc-antoine', 'marc-henri', 'marc-olivier', 'marceau', 'marcel', 'marcelin', 'marceline', 'marcelino', 'marcella', 'marcelle', 'marcellin', 'marcelline', 'marcello', 'marcelo', 'marcia', 'marcienne', 'marco', 'marcos', 'marcus', 'marek', 'mareva', 'margaret', 'margareth', 'margarida', 'margarita', 'margault', 'margaux', 'margo', 'margot', 'marguerite', 'marguerite-marie', 'margueritte', 'mari', 'maria', 'maria-carmen', 'maria-christina', 'maria-dolores', 'maria-fatima', 'maria-helena', 'maria-isabel', 'maria-jose', 'maria-luisa', 'maria-rosa', 'maria-teresa', 'mariam', 'mariama', 'mariame', 'marian', 'mariana', 'mariane', 'marianick', 'marianna', 'marianne', 'mariannick', 'mariano', 'maribel', 'marie', 'marie-adeline', 'marie-agnes', 'marie-aimee', 'marie-alice', 'marie-aline', 'marie-alix', 'marie-amandine', 'marie-amelie', 'marie-anais', 'marie-andree', 'marie-ange', 'marie-angelique', 'marie-angele', 'marie-anick', 'marie-anna', 'marie-anne', 'marie-annick', 'marie-annie', 'marie-antoinette', 'marie-armelle', 'marie-astrid', 'marie-aude', 'marie-aurore', 'marie-benedicte', 'marie-bernadette', 'marie-bernard', 'marie-berthe', 'marie-blanche', 'marie-brigitte', 'marie-beatrice', 'marie-camille', 'marie-carmen', 'marie-caroline', 'marie-catherine', 'marie-chantal', 'marie-charlotte', 'marie-christelle', 'marie-christiane', 'marie-christine', 'marie-claire', 'marie-claude', 'marie-claudine', 'marie-clotilde', 'marie-clemence', 'marie-colette', 'marie-cecile', 'marie-celine', 'marie-daniele', 'marie-danielle', 'marie-denise', 'marie-dolores', 'marie-dominique', 'marie-edith', 'marie-elisabeth', 'marie-elise', 'marie-elodie', 'marie-emilie', 'marie-emmanuelle', 'marie-estelle', 'marie-eugenie', 'marie-eve', 'marie-evelyne', 'marie-flore', 'marie-florence', 'marie-france', 'marie-francoise', 'marie-frederique', 'marie-gabrielle', 'marie-gaelle', 'marie-genevieve', 'marie-george', 'marie-georges', 'marie-germaine', 'marie-henriette', 'marie-helene', 'marie-isabelle', 'marie-jacqueline', 'marie-jeanne', 'marie-josee', 'marie-joseph', 'marie-josephe', 'marie-josephine', 'marie-josette', 'marie-josiane', 'marie-josephe', 'marie-jose', 'marie-josee', 'marie-joelle', 'marie-julie', 'marie-laetitia', 'marie-laure', 'marie-laurence', 'marie-liesse', 'marie-line', 'marie-lise', 'marie-lorraine', 'marie-lou', 'marie-louise', 'marie-lourdes', 'marie-luce', 'marie-lucie', 'marie-lyne', 'marie-lys', 'marie-lyse', 'marie-lea', 'marie-madeleine', 'marie-magdeleine', 'marie-marguerite', 'marie-marthe', 'marie-martine', 'marie-michelle', 'marie-michele', 'marie-monique', 'marie-nathalie', 'marie-neige', 'marie-nelly', 'marie-nicole', 'marie-noele', 'marie-noel', 'marie-noelle', 'marie-oceane', 'marie-odette', 'marie-odile', 'marie-pascale', 'marie-paule', 'marie-pauline', 'marie-pierre', 'marie-reine', 'marie-renee', 'marie-rose', 'marie-sarah', 'marie-solange', 'marie-sophie', 'marie-stephanie', 'marie-suzanne', 'marie-sylvie', 'marie-thereze', 'marie-therese', 'marie-victoire', 'marie-virginie', 'marie-veronique', 'marie-yvonne', 'marieke', 'mariella', 'marielle', 'mariem', 'marieme', 'marien', 'marietou', 'marietta', 'mariette', 'marika', 'marilene', 'mariline', 'marilou', 'marilyn', 'marilyne', 'marilys', 'marilyse', 'marin', 'marina', 'marine', 'marinella', 'marinette', 'marino', 'mario', 'marion', 'marisa', 'marise', 'marisol', 'marissa', 'maritchu', 'marius', 'marivonne', 'mariya', 'marjan', 'marjane', 'marjolaine', 'marjorie', 'marjory', 'mark', 'marko', 'markus', 'marla', 'marleine', 'marley', 'marline', 'marlise', 'marlon', 'marlone', 'marly', 'marlyse', 'marlene', 'marnie', 'maroine', 'maroua', 'marouan', 'marouane', 'maroussia', 'marta', 'martha', 'marthe', 'martial', 'martim', 'martin', 'martina', 'martine', 'marty', 'marveen', 'marvin', 'marvyn', 'marwa', 'marwan', 'marwane', 'marwen', 'marwin', 'mary', 'mary-line', 'mary-lou', 'marya', 'maryam', 'maryama', 'maryame', 'maryan', 'maryannick', 'maryem', 'marylaine', 'marylene', 'marylin', 'maryline', 'marylise', 'marylou', 'marylene', 'maryna', 'maryne', 'maryon', 'maryse', 'maryssa', 'maryvonne', 'mason', 'massi', 'massil', 'massilia', 'massilya', 'massimo', 'massinissa', 'massyl', 'matea', 'matei', 'mateo', 'mathea', 'matheis', 'matheo', 'mathew', 'mathias', 'mathieu', 'mathilda', 'mathilde', 'mathis', 'mathurin', 'mathurine', 'mathyas', 'mathylde', 'mathys', 'matheis', 'matheo', 'matheis', 'matias', 'matilda', 'matilde', 'matis', 'matiss', 'matisse', 'matt', 'mattea', 'matteo', 'mattew', 'mattheo', 'matthew', 'matthias', 'matthieu', 'matthis', 'matthys', 'mattheo', 'matti', 'mattia', 'mattias', 'mattieu', 'mattin', 'mattis', 'mattys', 'matteo', 'maty', 'matyas', 'matys', 'mateo', 'maud', 'maude', 'maurane', 'mauranne', 'maureen', 'maurice', 'mauricette', 'mauricia', 'maurille', 'maurin', 'maurine', 'maurizio', 'mauro', 'maverick', 'mavrick', 'max', 'maxance', 'maxandre', 'maxence', 'maxens', 'maxim', 'maxime', 'maximilian', 'maximilien', 'maximilienne', 'maximin', 'maxine', 'maxym', 'may', 'may-lee', 'may-line', 'maya', 'mayalen', 'mayana', 'mayane', 'mayar', 'mayeul', 'mayla', 'maylan', 'maylane', 'maylee', 'mayleen', 'mayli', 'maylie', 'mayline', 'maylis', 'mayliss', 'maylisse', 'maymouna', 'mayna', 'mayra', 'mayron', 'mayronn', 'maysa', 'maysan', 'mayson', 'mayssa', 'mayssam', 'mayssane', 'mazarine', 'mazen', 'mae', 'maelia', 'maelie', 'maeline', 'maely', 'maelya', 'maelyne', 'maelys', 'maeva', 'mae', 'mael', 'maela', 'maelan', 'maelane', 'maelann', 'maelia', 'maelie', 'maeline', 'maelis', 'maella', 'maelle', 'maelly', 'maellys', 'maely', 'maelya', 'maelyne', 'maelynn', 'maelys', 'maelyss', 'maelysse', 'maena', 'maeva', 'maia', 'mailane', 'maily', 'mailys', 'maimouna', 'maina', 'maira', 'maissa', 'maissane', 'maite', 'maiwen', 'maiwenn', 'medard', 'meddy', 'mederic', 'mederick', 'medhi', 'medhy', 'medi', 'medina', 'medine', 'medy', 'meg', 'megan', 'megane', 'meganne', 'meggane', 'meggie', 'meggy', 'meghan', 'meghane', 'meghann', 'meguy', 'mehdi', 'mehdy', 'mehmet', 'mei', 'meije', 'meir', 'meissa', 'meissane', 'mejdi', 'mekki', 'mel', 'melaine', 'melanie', 'melany', 'melchior', 'melda', 'melek', 'melia', 'meliana', 'meliane', 'melie', 'melih', 'meliha', 'melik', 'melika', 'melike', 'melina', 'melinda', 'meline', 'melis', 'melisa', 'melisande', 'melissa', 'melissande', 'melissandre', 'melisse', 'mellie', 'mellina', 'melodie', 'melody', 'meloe', 'meltem', 'melusine', 'melvil', 'melvin', 'melvina', 'melvine', 'melvyn', 'melwan', 'melya', 'melyna', 'melynda', 'melyne', 'melyssa', 'menahem', 'mendel', 'mendy', 'menel', 'menzo', 'meral', 'mercedes', 'meredith', 'meriam', 'meriem', 'merieme', 'merine', 'merlin', 'merouane', 'merry', 'merryl', 'merve', 'merveille', 'merwan', 'merwane', 'mery', 'meryam', 'meryem', 'meryl', 'meryll', 'mesmin', 'messaline', 'messaoud', 'messaouda', 'messi', 'messon', 'mesut', 'metehan', 'metin', 'meva', 'meven', 'mevlut', 'mewen', 'mewenn', 'meyline', 'meyssa', 'meziane', 'meissa', 'mia', 'micael', 'micaela', 'michael', 'michaela', 'michaele', 'michaella', 'michaelle', 'michael', 'michel', 'michel-ange', 'micheline', 'michelle', 'michele', 'mick', 'mickael', 'mickaela', 'mickaella', 'mickaelle', 'mickael', 'micky', 'mieczyslaw', 'miguel', 'mika', 'mikael', 'mikaela', 'mikail', 'mikael', 'mikail', 'mike', 'mikel', 'mikhael', 'mila', 'milan', 'milana', 'milane', 'milann', 'mildred', 'milena', 'milene', 'miley', 'milhan', 'milhane', 'milia', 'milian', 'miliana', 'milla', 'millie', 'milly', 'milo', 'milos', 'miloud', 'mily', 'milan', 'milene', 'milena', 'mimose', 'mimoun', 'mimouna', 'mina', 'mindy', 'minh', 'minna', 'mira', 'mirabelle', 'mirac', 'miral', 'miran', 'miranda', 'miray', 'mirac', 'mireille', 'mirella', 'miren', 'mirette', 'miriam', 'miriame', 'mirko', 'mirna', 'miryam', 'misha', 'miya', 'moana', 'moderan', 'modestine', 'modibo', 'mody', 'mohamad', 'mohamadou', 'mohamed', 'mohamed-ali', 'mohamed-amin', 'mohamed-amine', 'mohamed-lamine', 'mohamed-yacine', 'mohamed-yassine', 'mohammad', 'mohammed', 'mohammed-amine', 'mohand', 'moira', 'moise', 'moisette', 'mokhtar', 'mokrane', 'moktar', 'molly', 'mona', 'moncef', 'monette', 'monia', 'monica', 'monika', 'monique', 'monir', 'montaine', 'montserrat', 'morad', 'morade', 'moran', 'morane', 'morgan', 'morgane', 'morgann', 'morganne', 'morgiane', 'morine', 'morjane', 'morvan', 'mory', 'mostafa', 'mostapha', 'mouad', 'mouadh', 'moufida', 'mouhamad', 'mouhamadou', 'mouhamed', 'mouhammad', 'moulay', 'mouloud', 'mouna', 'mounia', 'mounir', 'mounira', 'mourad', 'mourade', 'moussa', 'moustafa', 'moustapha', 'moira', 'moise', 'muguette', 'muhamed', 'muhammad', 'muhammed', 'muhammed-ali', 'muhammet', 'murat', 'muriel', 'muriele', 'murielle', 'musa', 'mustafa', 'mustapha', 'my', 'mya', 'myah', 'myla', 'mylan', 'mylana', 'mylane', 'mylann', 'mylena', 'mylie', 'mylla', 'mylo', 'mylene', 'mylena', 'myriam', 'myriame', 'myriane', 'myrianne', 'myriem', 'myrna', 'myron', 'myrtille', 'medina', 'medine', 'mederic', 'megane', 'melaine', 'melanie', 'melany', 'melia', 'melie', 'melina', 'melinda', 'meline', 'melisande', 'melissa', 'melissandre', 'mellina', 'melodie', 'melody', 'meloe', 'melusine', 'melya', 'melyna', 'melyne', 'melyssa', 'meryl', 'mia', "n'deye", 'nabil', 'nabila', 'nabile', 'nabintou', 'nacer', 'nacera', 'nacim', 'nacima', 'nacira', 'nada', 'nadege', 'nadeige', 'nader', 'nadera', 'nadhir', 'nadia', 'nadiege', 'nadim', 'nadine', 'nadir', 'nadira', 'nadja', 'nadjet', 'nadji', 'nadjia', 'nadjib', 'nadjim', 'nady', 'nadya', 'nadege', 'nael', 'naela', 'naella', 'naelle', 'naema', 'nafissa', 'nafissatou', 'naguib', 'nahel', 'nahia', 'nahida', 'nahil', 'nahila', 'nahim', 'nahima', 'nahla', 'nahyl', 'nahel', 'naia', 'naida', 'nail', 'naila', 'naim', 'naima', 'nais', 'naissa', 'najah', 'najat', 'najate', 'najet', 'najette', 'naji', 'najia', 'najib', 'najim', 'najla', 'najma', 'najoua', 'najwa', 'nala', 'nalya', 'nana', 'nancy', 'nans', 'nao', 'naomi', 'naomie', 'naomy', 'naoual', 'naouel', 'naoufal', 'naoufel', 'napoleon', 'narcisse', 'narimane', 'narjes', 'narjess', 'narjis', 'narjisse', 'nasim', 'nasira', 'nasma', 'nasri', 'nasrine', 'nasser', 'nassera', 'nasserdine', 'nassim', 'nassima', 'nassime', 'nassira', 'nastasia', 'nastassia', 'natacha', 'natael', 'natale', 'natali', 'natalia', 'natalie', 'natalina', 'natan', 'natanael', 'natasha', 'nateo', 'nathael', 'nathalia', 'nathalie', 'nathaly', 'nathan', 'nathanael', 'nathanaelle', 'nathanael', 'nathanaelle', 'nathane', 'nathaniel', 'nathael', 'natheo', 'nathys', 'natheo', 'nattan', 'natty', 'nateo', 'nausicaa', 'nawal', 'nawale', 'nawel', 'nawell', 'nawelle', 'nawfal', 'nawfel', 'naya', 'nayah', 'nayan', 'nayel', 'nayeli', 'nayla', 'nazaire', 'nazha', 'naziha', 'nazim', 'nazli', 'nae', 'nael', 'naelle', 'naelya', 'naelys', 'naia', 'nail', 'naila', 'naim', 'naima', 'nais', 'naissa', 'ndeye', 'neal', 'nedjma', 'neela', 'nehemie', 'nehla', 'neige', 'neil', 'neila', 'nejla', 'nejma', 'nel', 'nelia', 'nelie', 'nelio', 'nell', 'nella', 'nellie', 'nello', 'nelly', 'nellya', 'nelson', 'nelya', 'nemo', 'nenad', 'nene', 'neo', 'nermine', 'neslihan', 'nesma', 'nesrin', 'nesrine', 'ness', 'nessa', 'nessim', 'nessrine', 'nesta', 'nestor', 'neva', 'neven', 'neyla', 'nezha', 'neila', 'ngoc', 'niame', 'nicaise', 'nicholas', 'nicky', 'nico', 'nicodeme', 'nicola', 'nicolas', 'nicole', 'nicoletta', 'nicolette', 'nicolle', 'nicomede', 'nida', 'nidal', 'nidhal', 'niels', 'nihad', 'nihal', 'nihed', 'nihel', 'nikita', 'nikola', 'nikolas', 'nil', 'nila', 'nilay', 'nilda', 'nils', 'nima', 'nina', 'nine', 'nino', 'ninon', 'niouma', 'nirina', 'nisa', 'nisanur', 'nisrine', 'nissa', 'nissrine', 'nita', 'nizar', 'noa', 'noah', 'noam', 'noan', 'noane', 'noann', 'noe', 'noela', 'noele', 'noelia', 'noelie', 'noeline', 'noelise', 'noella', 'noellie', 'noelline', 'noelly', 'noely', 'noelyne', 'noemi', 'noemie', 'noemy', 'noha', 'noham', 'nohan', 'nohann', 'nohe', 'nohlan', 'nohra', 'nohe', 'nola', 'nolan', 'nolane', 'nolann', 'nolhan', 'nolhann', 'nollan', 'nolwen', 'nolwenn', 'nonce', 'noor', 'nora', 'norah', 'norane', 'norbert', 'nordin', 'nordine', 'noredine', 'noreen', 'norhane', 'noria', 'noriane', 'norine', 'norma', 'norman', 'nouara', 'nouh', 'nouha', 'nouhaila', 'nour', 'nour-eddine', 'noura', 'nourane', 'nourdine', 'noureddine', 'nouredine', 'nourhane', 'nouria', 'nourredine', 'noussayba', 'noe', 'noelia', 'noelie', 'noeline', 'noelyne', 'noemi', 'noemie', 'noemy', 'noe', 'noel', 'noelie', 'noeline', 'noella', 'noelle', 'noellie', 'noelyne', 'noemie', 'numa', 'nuno', 'nunzia', 'nur', 'nuray', 'nurcan', 'nuria', 'nyla', 'nylan', 'nyls', 'nyna', 'nehemie', 'nelia', 'nelio', 'nelya', 'neo', 'ocean', 'oceana', 'oceane', 'oceanne', 'octave', 'octavie', 'oculi', 'oceane', 'oceanne', 'odelia', 'odeline', 'odessa', 'odette', 'odile', 'odille', 'odilon', 'odin', 'odon', 'odyle', 'oguz', 'oguzhan', 'oihan', 'oihana', 'okan', 'oksana', 'oktay', 'olfa', 'olga', 'oliana', 'olinda', 'oliva', 'olive', 'oliver', 'olivette', 'olivia', 'olivier', 'ollivier', 'olympe', 'omaima', 'omar', 'omayma', 'ombeline', 'ombline', 'omer', 'omerine', 'ondine', 'onesime', 'onur', 'oona', 'opale', 'opaline', 'ophelia', 'ophelie', 'opheline', 'ophely', 'ophelia', 'ophelie', 'orane', 'oren', 'oreste', 'orhan', 'oria', 'orian', 'oriana', 'oriane', 'orianna', 'orianne', 'orion', 'orlando', 'orlane', 'orlanne', 'ornela', 'ornella', 'orphee', 'orso', 'oscar', 'oskar', 'osman', 'osmin', 'ossama', 'oswald', 'othilie', 'othman', 'othmane', 'othon', 'otis', 'otman', 'otmane', 'otto', 'ouafa', 'ouahiba', 'ouahid', 'oualid', 'ouarda', 'ouardia', 'ouassila', 'ouassim', 'ouissem', 'ouiza', 'oulfa', 'oumaima', 'oumar', 'oumarou', 'oumayma', 'oumeyma', 'oumou', 'oumy', 'ourdia', 'ouria', 'ourida', 'ouriel', 'ours', 'ousman', 'ousmane', 'oussama', 'ouways', 'ovide', 'owen', 'owenn', 'oxana', 'ozan', 'ozcan', 'ozge', 'ozgur', 'ozkan', 'ozlem', 'pablo', 'paco', 'pacome', 'pacome', 'palmire', 'palmyre', 'paloma', 'pamela', 'pamela', 'paol', 'paola', 'paolina', 'paoline', 'paolo', 'papa', 'pape', 'paquerette', 'paquita', 'parfait', 'parfaite', 'pascal', 'pascale', 'pascaline', 'pasquale', 'patric', 'patrice', 'patricia', 'patricio', 'patrick', 'patrik', 'patrizia', 'patxi', 'paul', 'paul-adrien', 'paul-alexandre', 'paul-andre', 'paul-antoine', 'paul-arthur', 'paul-edouard', 'paul-emile', 'paul-emmanuel', 'paul-henri', 'paul-henry', 'paul-louis', 'paul-marie', 'paula', 'paule', 'paulette', 'paulin', 'paulina', 'pauline', 'paulo', 'pavel', 'pearl', 'pedro', 'peggy', 'peguy', 'peio', 'pelagie', 'pelin', 'penda', 'penelope', 'pepin', 'pepita', 'perine', 'perla', 'perle', 'perline', 'pernelle', 'peroline', 'perrine', 'pervenche', 'peter', 'petra', 'petronille', 'petrus', 'peyo', 'peyton', 'pharell', 'pharrell', 'philbert', 'phileas', 'philemon', 'philibert', 'philiberte', 'philip', 'philippa', 'philippe', 'philippine', 'philogone', 'philomene', 'philomene', 'phoebe', 'pia', 'pierina', 'piero', 'pierre', 'pierre-adrien', 'pierre-alain', 'pierre-alexandre', 'pierre-alexis', 'pierre-andre', 'pierre-antoine', 'pierre-arnaud', 'pierre-baptiste', 'pierre-charles', 'pierre-edouard', 'pierre-emmanuel', 'pierre-eric', 'pierre-etienne', 'pierre-francois', 'pierre-henri', 'pierre-henry', 'pierre-jean', 'pierre-julien', 'pierre-laurent', 'pierre-louis', 'pierre-loup', 'pierre-luc', 'pierre-marie', 'pierre-michel', 'pierre-nicolas', 'pierre-olivier', 'pierre-paul', 'pierre-philippe', 'pierre-yves', 'pierrette', 'pierric', 'pierrick', 'pierrine', 'pierrot', 'pietro', 'pilar', 'pinar', 'pio', 'placide', 'pol', 'precilia', 'precillia', 'prescilia', 'prescilla', 'prescillia', 'preston', 'priam', 'pricillia', 'primo', 'prince', 'princesse', 'prisca', 'priscilia', 'priscilla', 'priscille', 'priscillia', 'privat', 'priya', 'prosper', 'prune', 'prunelle', 'pulcherie', 'penelope', 'qassim', 'qays', 'quentin', 'quiterie', 'quitterie', 'quoc', 'rabah', 'rabha', 'rabia', 'rabiha', 'racha', 'rached', 'rachel', 'rachele', 'rachelle', 'rachid', 'rachida', 'rachide', 'racim', 'radegonde', 'radhia', 'radia', 'radija', 'radoine', 'radouan', 'radouane', 'rafael', 'rafaela', 'rafaele', 'rafaelle', 'rafael', 'raffael', 'raffaele', 'rafik', 'rafika', 'rahim', 'rahima', 'rahma', 'railey', 'raimond', 'raimonde', 'raissa', 'raja', 'rajaa', 'rajae', 'ralph', 'rama', 'ramata', 'ramatoulaye', 'ramazan', 'ramdane', 'rami', 'ramon', 'ramona', 'ramuntcho', 'ramy', 'ramzi', 'ramzy', 'rana', 'randa', 'randy', 'rani', 'rania', 'ranim', 'ranya', 'raouf', 'raoul', 'raphael', 'raphaela', 'raphaele', 'raphaella', 'raphaelle', 'raphael', 'raphaele', 'raphaelle', 'raquel', 'ratiba', 'raul', 'ravza', 'rawane', 'rayan', 'rayana', 'rayane', 'rayann', 'rayanne', 'rayen', 'rayhan', 'rayhana', 'rayhane', 'raymond', 'raymonde', 'raynal', 'raynald', 'rayyan', 'razane', 'razika', 'raissa', 'rebeca', 'rebecca', 'recep', 'reda', 'redha', 'redoine', 'redouan', 'redouane', 'redwan', 'redwane', 'regina', 'reginald', 'regis', 'rehan', 'reine', 'reine-claude', 'reine-marie', 'reinette', 'rejane', 'rejeanne', 'remi', 'remise', 'remo', 'remond', 'remonde', 'remy', 'renald', 'renaldo', 'renan', 'renata', 'renato', 'renaud', 'renelde', 'renelle', 'renette', 'renzo', 'rene', 'rene-claude', 'renee', 'resul', 'reyan', 'reyhan', 'reymond', 'reymonde', 'reynald', 'reza', 'riad', 'riadh', 'ricardo', 'riccardo', 'richard', 'richarde', 'ricky', 'rico', 'rida', 'ridha', 'ridvan', 'rigobert', 'rihab', 'riham', 'rihana', 'rihanna', 'rihem', 'riley', 'rim', 'rima', 'rime', 'rina', 'rinaldo', 'ringo', 'rino', 'rita', 'ritaj', 'ritchie', 'ritchy', 'ritej', 'rivka', 'riwan', 'riyad', 'rizlaine', 'rizlane', 'rizlene', 'roan', 'robert', 'roberta', 'roberte', 'robertine', 'roberto', 'robin', 'robinson', 'rocco', 'roch', 'rochdi', 'rocky', 'rodney', 'rodolph', 'rodolphe', 'rodrigo', 'rodrigue', 'rogatien', 'roger', 'rogerio', 'rohan', 'rokhaya', 'rokia', 'roland', 'rolande', 'rolf', 'rolland', 'rollande', 'romain', 'romaine', 'romaissa', 'roman', 'romance', 'romane', 'romann', 'romano', 'romaric', 'romayssa', 'romaissa', 'romeo', 'romie', 'romina', 'romuald', 'romy', 'romeo', 'ron', 'ronald', 'ronaldo', 'ronan', 'roni', 'ronnie', 'ronny', 'rony', 'rosa', 'rosa-maria', 'rosaire', 'rosalia', 'rosalie', 'rosaline', 'rosan', 'rosana', 'rosane', 'rosanna', 'rosanne', 'rosaria', 'rosario', 'rose', 'rose-aimee', 'rose-anne', 'rose-helene', 'rose-line', 'rose-marie', 'rose-may', 'roseline', 'rosella', 'roselyne', 'rosemarie', 'rosemary', 'rosemonde', 'rosetta', 'rosette', 'rosiane', 'rosie', 'rosina', 'rosine', 'rosita', 'rosy', 'roumayssa', 'rowan', 'roxana', 'roxane', 'roxanne', 'roy', 'roza', 'rozenn', 'rubben', 'ruben', 'rubens', 'rubis', 'ruby', 'ruddy', 'rudi', 'rudolf', 'rudolph', 'rudolphe', 'rudy', 'ruffin', 'rufin', 'rufine', 'rui', 'rukiye', 'rumeysa', 'ruth', 'ryad', 'ryan', 'ryane', 'ryann', 'rym', 'ryma', 'ryme', 'rebecca', 'reda', 'regine', 'regis', 'rejane', 'remi', 'remy', 'saad', 'saadi', 'saadia', 'saba', 'sabah', 'sabas', 'saber', 'sabiha', 'sabin', 'sabina', 'sabine', 'sabra', 'sabri', 'sabria', 'sabrina', 'sabrine', 'sabry', 'sacha', 'sadek', 'sadi', 'sadia', 'sadio', 'sael', 'safa', 'safaa', 'safae', 'safi', 'safia', 'safiatou', 'safir', 'safiya', 'safouane', 'safwan', 'safwane', 'safya', 'sahar', 'sahel', 'sahin', 'sahra', 'said', 'saida', 'saidou', 'saif', 'saina', 'saint', 'saint-ange', 'saint-jean', 'saint-martin', 'sainte', 'sainte-croix', 'saja', 'sajid', 'sajida', 'sakina', 'salah', 'salah-eddine', 'salaheddine', 'salamata', 'saleha', 'salem', 'salia', 'salif', 'salih', 'saliha', 'salim', 'salima', 'salimata', 'salimatou', 'salime', 'salimou', 'salina', 'saliou', 'sally', 'salma', 'salman', 'salmane', 'salome', 'salomee', 'salomon', 'salome', 'saloua', 'salsabil', 'salvador', 'salvator', 'salvatore', 'salwa', 'sam', 'samah', 'samanta', 'samantha', 'samar', 'samara', 'samba', 'samed', 'samet', 'sami', 'samia', 'samih', 'samiha', 'samir', 'samira', 'sammy', 'samra', 'samson', 'samuel', 'samuelle', 'samy', 'samya', 'sana', 'sanaa', 'sanae', 'sanah', 'sandie', 'sandra', 'sandrina', 'sandrine', 'sandro', 'sandy', 'sania', 'sanjay', 'sanna', 'santa', 'santiago', 'santina', 'santino', 'santo', 'sanya', 'saona', 'saphia', 'saphir', 'sara', 'sarah', 'saran', 'sarha', 'sarina', 'sarra', 'sarrah', 'sasa', 'sascha', 'sasha', 'saskia', 'satine', 'saturnin', 'saturnine', 'satya', 'saul', 'sauveur', 'savana', 'savanah', 'savanna', 'savannah', 'saveria', 'saverio', 'savinien', 'sawsane', 'sawsen', 'sawsene', 'saya', 'sayan', 'sayana', 'sayann', 'said', 'saida', 'saina', 'scarlett', 'scheherazade', 'scholastie', 'scholastique', 'scott', 'scotty', 'sean', 'sebastian', 'sebastien', 'sebastienne', 'seda', 'sedat', 'sefa', 'sefora', 'seher', 'seif', 'sekou', 'selda', 'selen', 'selena', 'selene', 'selenia', 'selia', 'selim', 'selima', 'selin', 'selina', 'selma', 'selman', 'selmen', 'selya', 'selyan', 'sema', 'semi', 'semia', 'semih', 'semra', 'sena', 'seny', 'sephora', 'septime', 'seraphie', 'seraphin', 'seraphine', 'serdar', 'serena', 'serge', 'serges', 'sergine', 'sergio', 'serhat', 'serife', 'serigne', 'serine', 'serkan', 'serpil', 'servais', 'servan', 'servane', 'servanne', 'seth', 'sevan', 'sevda', 'severin', 'severine', 'sevgi', 'sevim', 'sevrine', 'seydina', 'seydou', 'seyma', 'seynabou', 'shade', 'shaden', 'shahid', 'shahin', 'shahine', 'shahinez', 'shai', 'shaima', 'shaina', 'shainez', 'shaineze', 'shakira', 'shams', 'shana', 'shane', 'shanel', 'shanelle', 'shani', 'shania', 'shanice', 'shanna', 'shannen', 'shannon', 'shanon', 'shanone', 'shany', 'shanyce', 'shanys', 'sharleen', 'sharon', 'sharone', 'shaun', 'shauna', 'shawn', 'shayan', 'shayana', 'shayma', 'shayna', 'shayness', 'shaynez', 'shaynna', 'shaima', 'shaina', 'shainez', 'sheherazade', 'sheila', 'sheima', 'shelby', 'sheldon', 'shelly', 'shelsy', 'shems', 'shemsy', 'sherazade', 'sherine', 'sherley', 'sheryl', 'sheryne', 'sheyma', 'shirel', 'shirine', 'shirley', 'shona', 'shun', 'shyrel', 'sherazade', 'sherine', 'siam', 'siana', 'sibel', 'sibylle', 'sid', 'sid-ahmed', 'sidi', 'sidi-mohamed', 'sidney', 'sidoine', 'sidonie', 'sidra', 'sidy', 'siegfried', 'sienna', 'siga', 'sigismond', 'sigrid', 'siham', 'sihame', 'sihem', 'siheme', 'sila', 'silas', 'silia', 'siloe', 'siloe', 'silvain', 'silvana', 'silvano', 'silvere', 'silvia', 'silviane', 'silvie', 'silvio', 'silya', 'simao', 'simeon', 'simon', 'simon-pierre', 'simone', 'simonne', 'simplice', 'simeo', 'simeon', 'sina', 'sinai', 'sinan', 'sinai', 'sinda', 'sindy', 'sinem', 'siobhan', 'sira', 'sirin', 'sirine', 'siryne', 'siwar', 'sixte', 'sixtine', 'skander', 'slim', 'sliman', 'slimane', 'sloan', 'sloane', 'smael', 'smahane', 'smail', 'smain', 'snezana', 'soa', 'soan', 'soana', 'soane', 'soann', 'soanne', 'soazic', 'soazig', 'socrate', 'soen', 'sofia', 'sofian', 'sofiane', 'sofien', 'sofiene', 'sofya', 'sofyan', 'sofyane', 'soha', 'sohaib', 'soham', 'sohan', 'sohane', 'sohann', 'sohanne', 'sohayb', 'soheib', 'soheil', 'sohel', 'soizic', 'soizick', 'sokhna', 'sokona', 'solal', 'solan', 'solane', 'solange', 'solann', 'soleane', 'soledad', 'solen', 'solena', 'solene', 'solenn', 'solenne', 'soline', 'solveig', 'solyne', 'solene', 'soleane', 'somaya', 'somia', 'soner', 'songul', 'sonia', 'sonja', 'sonny', 'sony', 'sonya', 'sophia', 'sophian', 'sophiane', 'sophie', 'sophien', 'soraya', 'soren', 'sorenza', 'soria', 'sory', 'sorya', 'sosthene', 'sosthenes', 'souad', 'souade', 'soufian', 'soufiane', 'soufyane', 'souhaib', 'souhail', 'souhaila', 'souhayl', 'souhayla', 'souheil', 'souheila', 'souheyl', 'souhil', 'souhila', 'soujoud', 'soukaina', 'soukayna', 'soukaina', 'soukeina', 'soukeyna', 'soulaimane', 'soulayman', 'soulaymane', 'soulef', 'souleyman', 'souleymane', 'souleymen', 'soumaya', 'soumayya', 'soumeya', 'soumia', 'soumiya', 'soumya', 'soundous', 'souraya', 'souria', 'sovann', 'soen', 'stacey', 'stacie', 'stacy', 'stan', 'stanis', 'stanislas', 'stanislaw', 'stanislawa', 'stanley', 'stann', 'stany', 'stecy', 'steeve', 'steeven', 'steevens', 'steevy', 'stefan', 'stefania', 'stefanie', 'stefano', 'stefen', 'steffi', 'steffie', 'steffy', 'stella', 'stelly', 'stephan', 'stephane', 'stephania', 'stephano', 'stephany', 'stephen', 'stephie', 'stephy', 'sterenn', 'stessie', 'stessy', 'stevan', 'steve', 'steven', 'stevens', 'stevie', 'stevy', 'stive', 'stiven', 'styven', 'steve', 'stephan', 'stephane', 'stephanie', 'stephen', 'sulayman', 'suleyman', 'sulivan', 'sullivan', 'sully', 'sullyvan', 'sulpice', 'sultan', 'sultana', 'sulyvan', 'sumeyye', 'summer', 'suna', 'sunny', 'susan', 'susana', 'susanne', 'susie', 'suzan', 'suzana', 'suzane', 'suzanna', 'suzanne', 'suzel', 'suzelle', 'suzette', 'suzie', 'suzon', 'suzy', 'sven', 'svetlana', 'swan', 'swane', 'swann', 'swanny', 'swany', 'swen', 'syana', 'sybil', 'sybile', 'sybille', 'sydney', 'sylia', 'sylva', 'sylvain', 'sylvaine', 'sylvana', 'sylvanie', 'sylvano', 'sylver', 'sylvere', 'sylvestre', 'sylvette', 'sylvia', 'sylvian', 'sylviana', 'sylviane', 'sylvianne', 'sylvie', 'sylvina', 'sylvine', 'sylvio', 'symphorien', 'syndie', 'synthia', 'syrielle', 'syrine', 'sebastien', 'segolene', 'selim', 'selene', 'selena', 'selenia', 'sephora', 'seraphin', 'seraphine', 'serine', 'serena', 'sevan', 'severine', 'soren', 'tabatha', 'tacko', 'tadeusz', 'taha', 'tahar', 'tahina', 'tahira', 'tahis', 'taho', 'tahys', 'taieb', 'taina', 'tais', 'tal', 'talha', 'tali', 'talia', 'talina', 'taline', 'talya', 'tamara', 'tamim', 'tanais', 'tancrede', 'tangi', 'tangui', 'tanguy', 'tania', 'tanina', 'tanya', 'tao', 'taoufik', 'taous', 'tara', 'tarak', 'tarek', 'tarik', 'tariq', 'taslim', 'tasnim', 'tasnime', 'tassadit', 'tatiana', 'tatyana', 'tayeb', 'taylan', 'tayler', 'taylor', 'tayna', 'tayron', 'tayson', 'tayssir', 'taina', 'tais', 'tea', 'ted', 'teddy', 'tedy', 'teeyah', 'tehani', 'teiva', 'telio', 'telma', 'tennessee', 'teo', 'teoman', 'terence', 'teresa', 'terrence', 'terry', 'tesnim', 'tesnime', 'tess', 'tessa', 'tessy', 'teva', 'tewfik', 'thaddee', 'thadee', 'thaina', 'thais', 'thalia', 'thalie', 'thalya', 'thanh', 'thanina', 'thao', 'thays', 'thais', 'thea', 'theana', 'theau', 'thelio', 'thelma', 'themis', 'theo', 'theodora', 'theodore', 'theodorine', 'theodose', 'theodule', 'theophane', 'theophile', 'theotime', 'theresa', 'theresia', 'theresien', 'theresine', 'thereze', 'thery', 'thessa', 'thi', 'thia', 'thiago', 'thibaud', 'thibauld', 'thibault', 'thibaut', 'thibo', 'thiebaut', 'thiefaine', 'thierno', 'thierry', 'thiery', 'thifaine', 'thimeo', 'thimote', 'thimothee', 'thimeo', 'thiphaine', 'thom', 'thomas', 'thomassine', 'thony', 'thuy', 'thya', 'thylane', 'thymeo', 'thymeo', 'thea', 'thelio', 'themis', 'theo', 'theodore', 'theophane', 'theophile', 'theotime', 'therese', 'therese-marie', 'tia', 'tiago', 'tiana', 'tibo', 'tiburce', 'tidiane', 'tidjane', 'tifaine', 'tifanie', 'tifanny', 'tifany', 'tifenn', 'tiffaine', 'tiffanie', 'tiffany', 'tiffen', 'tigane', 'tiguidanke', 'tijani', 'tilia', 'tilian', 'tilio', 'till', 'tim', 'timael', 'timao', 'timae', 'timael', 'timea', 'timeo', 'timmy', 'timo', 'timoleon', 'timon', 'timote', 'timotei', 'timothe', 'timothee', 'timothey', 'timothy', 'timothe', 'timothee', 'timoty', 'timote', 'timour', 'timy', 'timea', 'timeo', 'tina', 'tino', 'tiphaine', 'tiphanie', 'tiphany', 'tito', 'titouan', 'tiya', 'tiziana', 'tiziano', 'toan', 'tobias', 'tolga', 'tom', 'toma', 'tomas', 'tommy', 'tomy', 'toni', 'tonia', 'tonin', 'tonino', 'tonio', 'tonny', 'tony', 'tosca', 'toscane', 'toufik', 'touria', 'toussaint', 'toussainte', 'toussine', 'tracy', 'travis', 'trecy', 'tressy', 'trevis', 'trevor', 'tricia', 'trinidad', 'trinite', 'trinity', 'tristan', 'trystan', 'tsipora', 'tuana', 'tuba', 'tugba', 'tugdual', 'tulay', 'turenne', 'txomin', 'tya', 'tyago', 'tyana', 'tyfenn', 'tyffanie', 'tylan', 'tyler', 'tylia', 'tylian', 'tyliann', 'tylio', 'tymeo', 'tymeo', 'tyno', 'typhaine', 'typhanie', 'tyron', 'tyrone', 'tyson', 'tea', 'telio', 'teo', 'terence', 'ufuk', 'ugo', 'ugur', 'ulric', 'ulrich', 'ulrick', 'ulysse', 'uma', 'umberto', 'umit', 'umut', 'unai', 'uranie', 'urbain', 'uriel', 'urielle', 'ursula', 'ursule', 'vadim', 'vaiana', 'valene', 'valentin', 'valentina', 'valentine', 'valentino', 'valere', 'valeria', 'valerian', 'valeriane', 'valerien', 'valerine', 'valerio', 'valery', 'valter', 'valerian', 'valerie', 'valery', 'van', 'vanda', 'vanessa', 'vania', 'vanille', 'vanina', 'vannina', 'vasco', 'vassili', 'vassily', 'veli', 'venant', 'venceslas', 'venise', 'venus', 'vera', 'verane', 'verena', 'veronica', 'veronika', 'vesna', 'vianney', 'vicenta', 'vicente', 'vicenzo', 'vickie', 'vicky', 'victoire', 'victor', 'victoria', 'victorien', 'victorin', 'victorine', 'viggo', 'viktor', 'viktoria', 'vilma', 'vince', 'vincent', 'vincente', 'vincenza', 'vincenzo', 'vinciane', 'violaine', 'violene', 'violeta', 'violetta', 'violette', 'virgil', 'virgile', 'virgina', 'virginia', 'virginie', 'vital', 'vitaline', 'vito', 'vitor', 'vittoria', 'vittorio', 'vivette', 'vivian', 'viviane', 'vivianne', 'vivien', 'vivienne', 'vlad', 'vladimir', 'volkan', 'voltaire', 'veronique', 'wacil', 'wael', 'wafa', 'wafaa', 'wafae', 'wahib', 'wahiba', 'wahid', 'wahil', 'wail', 'wajdi', 'waldemar', 'walid', 'wally', 'walter', 'waly', 'wanda', 'wandrille', 'wanis', 'warda', 'waren', 'warren', 'wassil', 'wassila', 'wassim', 'wassima', 'wassime', 'wayan', 'wayatt', 'wayne', 'wael', 'wail', 'wenceslas', 'wendie', 'wendy', 'werner', 'wesley', 'whitney', 'wiam', 'wiame', 'widad', 'wided', 'wiem', 'wijdane', 'wilfrid', 'wilfried', 'wilhelm', 'wilhelmine', 'wilhem', 'will', 'willem', 'willi', 'william', 'williams', 'willow', 'willy', 'wilma', 'wilson', 'windy', 'winona', 'wissal', 'wissam', 'wissem', 'withney', 'wladimir', 'wladislas', 'wladislaw', 'wladislawa', 'wladyslas', 'wladyslaw', 'wladyslawa', 'wolfgang', 'wyatt', 'wylan', 'xabi', 'xan', 'xavier', 'xaviere', 'yacin', 'yacine', 'yacoub', 'yacouba', 'yael', 'yaelle', 'yagmur', 'yahia', 'yahya', 'yakine', 'yakup', 'yamin', 'yamina', 'yamine', 'yamna', 'yan', 'yana', 'yanael', 'yanael', 'yanel', 'yani', 'yanice', 'yanick', 'yanik', 'yanis', 'yaniss', 'yanisse', 'yaniv', 'yann', 'yanna', 'yanne', 'yanni', 'yannic', 'yannick', 'yannig', 'yannik', 'yannis', 'yara', 'yaren', 'yasar', 'yasemin', 'yasin', 'yasine', 'yasmin', 'yasmina', 'yasmine', 'yasser', 'yassin', 'yassine', 'yassir', 'yassmine', 'yavuz', 'yaya', 'yazid', 'yael', 'yaelle', 'ydriss', 'yelena', 'yeliz', 'yesmine', 'yigit', 'yilmaz', 'ylan', 'ylana', 'ylane', 'ylann', 'ylenzo', 'ylhan', 'ylian', 'yliana', 'ylias', 'ylies', 'yliess', 'yllan', 'ylona', 'ynes', 'yness', 'ynes', 'yoan', 'yoann', 'yoanna', 'yoanne', 'yoel', 'yoen', 'yohan', 'yohann', 'yohanna', 'yola', 'yolaine', 'yolan', 'yoland', 'yolanda', 'yolande', 'yolann', 'yolene', 'yon', 'yona', 'yonathan', 'yoni', 'yonis', 'yonni', 'yoram', 'yoran', 'yorick', 'yoris', 'yosra', 'yossef', 'youcef', 'youen', 'youenn', 'youmna', 'youn', 'youna', 'younes', 'youness', 'younesse', 'younous', 'younes', 'youri', 'yousef', 'yousra', 'yousri', 'youssef', 'youssouf', 'youssra', 'yovan', 'ysaline', 'yse', 'ysee', 'yseult', 'ysia', 'yssa', 'ysee', 'yumi', 'yuna', 'yunus', 'yunus-emre', 'yuri', 'yusra', 'yusuf', 'yvain', 'yvan', 'yvana', 'yvane', 'yvann', 'yvanna', 'yvanne', 'yveline', 'yvelise', 'yvelyne', 'yves', 'yves-marie', 'yvette', 'yvon', 'yvone', 'yvonne', 'yvonnette', 'yvonnick', 'yelena', 'zachari', 'zacharia', 'zacharie', 'zachary', 'zack', 'zackaria', 'zackary', 'zadig', 'zahia', 'zahir', 'zahira', 'zahra', 'zaia', 'zaid', 'zaina', 'zainab', 'zaineb', 'zakari', 'zakaria', 'zakariya', 'zakary', 'zakarya', 'zaki', 'zakia', 'zara', 'zayan', 'zayd', 'zayn', 'zayna', 'zaynab', 'zayneb', 'zaid', 'zaim', 'zaina', 'zdzislaw', 'zehra', 'zeina', 'zeinab', 'zeineb', 'zelal', 'zelda', 'zelia', 'zelie', 'zeliha', 'zenaide', 'zenon', 'zephir', 'zephirin', 'zephyr', 'zeyd', 'zeynab', 'zeyneb', 'zeynep', 'zia', 'ziad', 'zian', 'ziane', 'zidane', 'zied', 'zilan', 'zina', 'zine', 'zineb', 'zineddine', 'zinedine', 'zita', 'ziyad', 'ziyed', 'zoe', 'zoelie', 'zoey', 'zofia', 'zohra', 'zola', 'zora', 'zorah', 'zoran', 'zoubida', 'zoubir', 'zouhair', 'zouhir', 'zouina', 'zoulikha', 'zoya', 'zoe', 'zoelie', 'zoe', 'zulma', 'zya', 'zyad', 'zyed', 'zygmund', 'zygmunt', 'zelia', 'zelie', 'eve', 'eden', 'edouard', 'elena', 'elia', 'eliane', 'elias', 'elie', 'elina', 'eline', 'elio', 'eliot', 'eliott', 'elisa', 'elisabeth', 'elise', 'eloane', 'elodie', 'eloi', 'elouan', 'eloise', 'elya', 'elyna', 'elyne', 'elea', 'eleana', 'eleanore', 'elena', 'eleonore', 'emeline', 'emie', 'emile', 'emilie', 'emilien', 'emy', 'enola', 'enora', 'eric', 'erine', 'ethan', 'etienne', 'eva', 'evan', 'evelyne', 'omer'], resample=False, n_jobs=1, progress_bar=False, copy=True, n_max_keywords=6, n_min_keywords=0, threshold_keywords=0.0, n_docs_in_class=100, keywords_coef=10)[source]¶
Bases:
sklearn.base.BaseEstimator
,sklearn.base.TransformerMixin
Class to extract list of keywords from text.
It is compatible with scikit-learn API (i.e. contains fit, transform methods).
- Parameters
- max_tfidf_featuresint, optional
Size of vocabulary for tfidf. Default value, 10000.
- keywordslist, optional
Keywords to extracted as priority. Default value, “keywords” list defined in conf file.
- stopwordslist, optional
Stopwords not to be extracted. Default value, “names” and “stopwords” lists defined in conf file.
- resamplebool, optional
True if dataset must be resampled according to class distribution, else False. Default value, True.
- n_jobsint, optional
Number of cores used for computation. Default value, 20.
- copybool, optional
Make a copy of DataFrame. Default value, True.
- n_max_keywordsint, optional
Maximum number of keywords to be returned. Default value, 6.
- n_min_keywordsint, optional
Minimum number of keywords to be returned. Default value, 0.
- threshold_keywordsfloat, optional
Minimum tf-idf score for word to be selected as keyword. Default value, 0.0.
- n_docs_in_classint, optional
Number of documents in each classes. Default value, 100.
- keywords_coefint, optional
Coefficient multiplied with the tf-idf scores of each keywords. Default value, 10.
Examples
>>> from melusine.summarizer.keywords_generator import KeywordsGenerator >>> keywords_generator = KeywordsGenerator() >>> keywords_generator.fit(X, y) >>> keywords_generator.transform(X) >>> print(X['keywords'])
- Attributes
- max_tfidf_features, keywords, stopwords, resample, n_jobs, progress_bar,
- copy, n_max_keywords, n_min_keywords, threshold_keywords, n_docs_in_class,
- keywords_coef,
- tfidf_vectorizerTfidfVectorizer instance from sklearn,
- dict_scores_dictionary,
Tf-idf scores for each tokens.
- max_score_np.array,
- fit(X, y=None)[source]¶
Fit the weighted tf-idf model with input data.
If resample attribute is True the dataset will be resampled according to class distribution.
- Parameters
- Xpandas.DataFrame, shape (n_samples, n_features)
X must contain [‘tokens’] column.
- yIgnored
- Returns
- selfobject
Returns the instance itself.
Models subpackage melusine.models
¶
TODO : ADD DESCRIPTION OF THE SUBPACKAGE
List of submodules¶
NeuralArchitectures melusine.models.neural_architectures
¶
- melusine.models.neural_architectures.bert_model(ntargets=18, seq_max=100, nb_meta=134, loss='categorical_crossentropy', activation='softmax', bert_model='jplu/tf-camembert-base')[source]¶
Pre-defined architecture of a pre-trained Bert model.
- Parameters
- ntargetsint, optional
Dimension of model output. Default value, 18.
- seq_maxint, optional
Maximum input length. Default value, 100.
- nb_metaint, optional
Dimension of meta data input. Default value, 252.
- lossstr, optional
Loss function for training. Default value, ‘categorical_crossentropy’.
- activationstr, optional
Activation function. Default value, ‘softmax’.
- bert_modelstr, optional
Model name from HuggingFace library or path to local model Only Camembert and Flaubert supported Default value, ‘camembert-base’
- Returns
- Model instance
- melusine.models.neural_architectures.cnn_model(embedding_matrix_init, ntargets, seq_max, nb_meta, loss='categorical_crossentropy', activation='softmax')[source]¶
Pre-defined architecture of a CNN model.
- Parameters
- embedding_matrix_initnp.array,
Pretrained embedding matrix.
- ntargetsint, optional
Dimension of model output. Default value, 18.
- seq_maxint, optional
Maximum input length. Default value, 100.
- nb_metaint, optional
Dimension of meta data input. Default value, 252.
- lossstr, optional
Loss function for training. Default value, ‘categorical_crossentropy’.
- activationstr, optional
Activation function. Default value, ‘softmax’.
- Returns
- Model instance
- melusine.models.neural_architectures.rnn_model(embedding_matrix_init, ntargets=18, seq_max=100, nb_meta=252, loss='categorical_crossentropy', activation='softmax')[source]¶
Pre-defined architecture of a RNN model.
- Parameters
- embedding_matrix_initnp.array,
Pretrained embedding matrix.
- ntargetsint, optional
Dimension of model output. Default value, 18.
- seq_maxint, optional
Maximum input length. Default value, 100.
- nb_metaint, optional
Dimension of meta data input. Default value, 252.
- lossstr, optional
Loss function for training. Default value, ‘categorical_crossentropy’.
- activationstr, optional
Activation function. Default value, ‘softmax’.
- Returns
- Model instance
- melusine.models.neural_architectures.transformers_model(embedding_matrix_init, ntargets=18, seq_max=100, nb_meta=134, loss='categorical_crossentropy', activation='softmax')[source]¶
Pre-defined architecture of a Transformer model.
- Parameters
- embedding_matrix_initnp.array,
Pretrained embedding matrix.
- ntargetsint, optional
Dimension of model output. Default value, 18.
- seq_maxint, optional
Maximum input length. Default value, 100.
- nb_metaint, optional
Dimension of meta data input. Default value, 252.
- lossstr, optional
Loss function for training. Default value, ‘categorical_crossentropy’.
- activationstr, optional
Activation function. Default value, ‘softmax’.
- Returns
- Model instance
Train melusine.models.train
¶
- class melusine.models.train.NeuralModel[source]¶
Bases:
sklearn.base.BaseEstimator
,sklearn.base.ClassifierMixin
Generic class for neural models.
It is compatible with scikit-learn API (i.e. contains fit, transform methods).
- Parameters
- neural_architecture_functionfunction,
Function which returns a Model instance from Keras. Implemented model functions are: cnn_model, rnn_model, transformers_model, bert_model
- pretrained_embeddingnp.array,
Pretrained embedding matrix.
- text_input_columnstr,
Input text column to consider for the model.
- meta_input_listlist, optional
List of the names of the columns containing the metadata. If empty list or None the model is used without metadata Default value, [‘extension’, ‘dayofweek’, ‘hour’, ‘min’].
- vocab_sizeint, optional
Size of vocabulary for neurol network model. Default value, 25000.
- seq_sizeint, optional
Maximum size of input for neural model. Default value, 100.
- lossstr, optional
Loss function for training. Default value, ‘categorical_crossentropy’.
- activationstr, optional
Activation function. Default value, ‘softmax’.
- batch_sizeint, optional
Size of batches for the training of the neural network model. Default value, 4096.
- n_epochsint, optional
Number of epochs for the training of the neural network model. Default value, 15.
- bert_tokenizerstr, optional
Tokenizer name from HuggingFace library or path to local tokenizer Only Camembert and Flaubert supported Default value, ‘camembert-base’
- bert_modelstr, optional
Model name from HuggingFace library or path to local model
Only Camembert and Flaubert supported Default value, ‘camembert-base’
Examples
>>> from melusine.models.train import NeuralModel >>> from melusine.models.neural_architectures import cnn_model >>> from melusine.nlp_tools.embedding import Embedding >>> pretrained_embedding = Embedding.load() >>> list_meta = ['extension', 'dayofweek', 'hour'] >>> nn_model = NeuralModel(cnn_model, pretrained_embedding, list_meta) #noqa >>> nn_model.fit(X_train, y_train) #noqa >>> y_res = nn_model.predict(X_test) #noqa
- Attributes
- architecture_function, pretrained_embedding, text_input_column,
- meta_input_list, vocab_size, seq_size, loss, batch_size, n_epochs,
- modelModel instance from Keras,
- tokenizerTokenizer instance from Melusine,
- embedding_matrixnp.array,
Embedding matrix used as input for the neural network model.
- fit(X_train, y_train, tensorboard_log_dir=None, validation_data=None, **kwargs)[source]¶
Fit the neural network model on X and y. If meta_input list is empty list or None the model is used without metadata.
Compatible with scikit-learn API.
- Parameters
- X_trainpd.DataFrame
- y_trainpd.Series
- tensorboard_log_dirstr
If not None, will be used as path to write logs for tensorboard Tensordboard callback parameters can be changed in config file
- validation_data: tuple
Tuple of validation data Data on which to evaluate the loss and any model metrics at the end of each epoch. The model will not be trained on this data. This could be a tuple (x_val, y_val). validation_data will override validation_split. Default value, None.
- Returns
- selfobject
Returns the instance
- predict_proba(X, **kwargs)[source]¶
Returns the probabilities associated to each classes. If meta_input list is empty list or None the model is used without metadata.
- Parameters
- Xpd.DataFrame
- prediction_intervalfloat, optional
between [0,1], the confidence level of the interval. Only available with tensorflow-probability models.
- Returns
- ——-
- scorenp.array
The estimation of probability for each category.
- infnp.array, optional
The upper bound of the estimation of probability. Only provided if prediction_interval exists.
- supnp.array, optional
The lower bound of the estimation of probability. Only provided if prediction_interval exists.
- prepare_email_to_predict(X)[source]¶
Returns the email as a compatible shape wich depends on the type of neural model
- Parameters
- Xpd.DataFrame
- Returns
- list
List of the inputs to the neural model Either [X_seq] if no metadata Or [X_seq, X_meta] if metadata Or [X_seq, X_attention, X_meta] if Bert model
Config subpackage melusine.config
¶
TODO : ADD DESCRIPTION OF THE SUBPACKAGE
List of submodules¶
Config melusine.config.config
¶
- class melusine.config.config.MelusineConfig[source]¶
Bases:
object
The MelusineConfig class acts as a dict containing configurations. The configurations can be changed dynamically using the switch_config function.
- load_melusine_conf() None [source]¶
Load the melusine configurations. The default configurations are loaded first (the one present in the melusine package). Custom configurations may overwrite the default ones. Custom configuration should be specified in YML and JSON files and placed in a directory. The directory path should be set as the value of the MELUSINE_CONFIG_DIR environment variable. Returns ——- conf: dict
Loaded config dict
- melusine.config.config.config_deprecation_warnings(config_dict: Dict[str, Any]) None [source]¶
Raise Deprecation Warning when using deprecated configs
- melusine.config.config.load_conf_from_path(config_dir_path: str) Dict[str, Any] [source]¶
Given a directory path Parameters ———- config_dir_path: str
Path to a directory containing YML or JSON conf files
- conf: dict
Loaded config dict
- melusine.config.config.switch_config(new_config)[source]¶
Function to change the Melusine configuration using a dict.
- Parameters
- new_config: dict
Dict containing the new config
- melusine.config.config.update_nested_dict(base_dict: dict, update_dict: dict) dict [source]¶
Update a (possibly) nested dictionary using another (possibly) nested dictionary. Ex:
base_dict = {“A”: {“a”: “0”}} u = {“A”: {“b”: “42”}} update_dict = update_nested_dict(d, u) # Output : {“A”: {“a”: “0”, “b”: “42”}}
- Parameters
- base_dict: Mapping
Base dict to be updated
- update_dict: Mapping
Update dict to merge into d
- Returns
- base_dict: Mapping
Updated dict
Contributing¶
Contributions are welcome, and they are greatly appreciated! Every little bit helps, and credit will always be given.
You can contribute in many ways:
Types of Contributions¶
Report Bugs¶
Report bugs at https://github.com/MAIF/melusine/issues.
If you are reporting a bug, please include:
Your operating system name and version.
Any details about your local setup that might be helpful in troubleshooting.
Detailed steps to reproduce the bug.
Fix Bugs¶
Look through the GitHub issues for bugs. Anything tagged with “bug” and “help wanted” is open to whoever wants to implement it.
Implement Features¶
Look through the GitHub issues for features. Anything tagged with “enhancement” and “help wanted” is open to whoever wants to implement it.
Write Documentation¶
Amabie could always use more documentation, whether as part of the official melusine docs, in docstrings, or even on the web in blog posts, articles, and such.
Submit Feedback¶
The best way to send feedback is to file an issue at https://github.com/MAIF/melusine/issues.
If you are proposing a feature:
Explain in detail how it would work.
Keep the scope as narrow as possible, to make it easier to implement.
Remember that this is a volunteer-driven project, and that contributions are welcome :)
Get Started!¶
Ready to contribute? Here’s how to set up melusine for local development.
Fork the melusine repo on GitHub.
Clone your fork locally:
$ git clone git@github.com:your_name_here/melusine.git
Install your local copy into a virtualenv. Assuming you have virtualenvwrapper installed, this is how you set up your fork for local development:
$ mkvirtualenv melusine $ cd melusine/ $ python setup.py develop
Create a branch for local development:
$ git checkout -b name-of-your-bugfix-or-feature
Now you can make your changes locally.
When you’re done making changes, check that your changes pass flake8 and the tests, including testing other Python versions with tox:
$ flake8 melusine tests $ python setup.py test or py.test $ tox
To get flake8 and tox, just pip install them into your virtualenv.
Commit your changes and push your branch to GitHub:
$ git add . $ git commit -m "Your detailed description of your changes." $ git push origin name-of-your-bugfix-or-feature
Submit a pull request through the GitHub website.
Pull Request Guidelines¶
Before you submit a pull request, check that it meets these guidelines:
The pull request should include tests.
If the pull request adds functionality, the docs should be updated. Put your new functionality into a function with a docstring, and add the feature to the list in README.rst.
The pull request should work for Python 2.7, 3.4, 3.5 and 3.6, and for PyPy. Check https://travis-ci.org/sachasamama/melusine/pull_requests and make sure that the tests pass for all supported Python versions.
Tips¶
To run a subset of tests:
$ py.test tests.test_melusine
Deploying¶
A reminder for the maintainers on how to deploy. Make sure all your changes are committed (including an entry in HISTORY.rst). Then run:
$ bumpversion patch # possible: major / minor / patch
$ git push
$ git push --tags
Travis will then deploy to PyPI if tests pass.
Credits¶
Development Lead (Quantmetry Team support Maif Team)¶
Sacha Samama
Tom Stringer
Antoine Simoulin <asimoulin@quantmetry.com>
Benoit Lebreton <blebreton@quantmetry.com>
Contributors¶
Florian Arthur <farthur@quantmetry.com>
Fabre Tiphaine <tiphaine.fabre@maif.fr>
Marouane Il Idrissi <ilidrissi.m@gmail.com>
Hugo Perrier <hperrier@quantmetry.com>
Victor Bigand <vbigand@quantmetry.com>
To be continued …