Boy or Girl? A Machine Learning Web App to Detect Gender from Name | by Marie Stephen Leo | Towards Data Science

Choosing a name for your child is one of the most stressful decisions you’ll have to make as a new parent. Especially for a data-driven guy like me, having to decide on a name without any prior data about my child’s character and preferences is a nightmare come true!
Since my first name starts with “Marie,” I’ve gone through countless experiences of people addressing me as “Miss” over emails and text only to be disappointed to realize that I’m actually a guy when we finally meet or talk 😜. So, when my wife and I were researching names for our baby girl, an important question we asked ourselves was:
Will people be able to identify that the name refers to a girl and not a boy?
It turns out we can use Machine Learning to help us check if potential names would be associate more with boys or girls! To check out the app I’ve built to do exactly this, please head over to https://www.boyorgirl.xyz.
The rest of this post talks about the technical details, including
Obtaining a name to the gender training datasetPreprocessing the names to make them compatible with Machine Learning (ML) modelsDeveloping a Natural Language Processing (NLP) ML model to read in a name and output if it’s a boy’s name or a girl’s nameBuilding a simple web app for people to interact with the modelPublishing the app on the internet
Obtaining a name to the gender training dataset
Preprocessing the names to make them compatible with Machine Learning (ML) models
Developing a Natural Language Processing (NLP) ML model to read in a name and output if it’s a boy’s name or a girl’s name
Building a simple web app for people to interact with the model
Publishing the app on the internet
To train any Machine Learning model, we need a large quantity of labeled data. In this case, we need a large number of names and the associated gender of that name. Luckily, Google Cloud’s Bigquery has a free open dataset called USA_NAMES [Link] that “contains all names from Social Security card applications for births that occurred in the United States.” The dataset contains roughly 35000 names and the associated gender, which works very well for our model.
Human names are textual data, while ML models can only work with numeric data. To convert our text into a numeric representation, we’ll do the following steps.
Lowercase the name since each character’s case doesn’t convey any information about a person’s gender.Split each character: The basic idea of the ML model we’re building is to read characters in a name to identify patterns that could indicate masculinity or femininity. Thus we split the name into each character.Pad names with empty spaces until a max of 50 characters ensures the ML model sees the same length for all the names.Encode each character to a unique number since ML models can only work with numbers. In this case, we encode ‘ ’ (space) to 0, ‘a’ to 1, ‘b’ to 2, and so on.Encode each gender to a unique number since ML models can only work with numbers. In this case, we encode ‘F’ to 0 and ‘M’ to 1.
Lowercase the name since each character’s case doesn’t convey any information about a person’s gender.
Split each character: The basic idea of the ML model we’re building is to read characters in a name to identify patterns that could indicate masculinity or femininity. Thus we split the name into each character.
Pad names with empty spaces until a max of 50 characters ensures the ML model sees the same length for all the names.
Encode each character to a unique number since ML models can only work with numbers. In this case, we encode ‘ ’ (space) to 0, ‘a’ to 1, ‘b’ to 2, and so on.
Encode each gender to a unique number since ML models can only work with numbers. In this case, we encode ‘F’ to 0 and ‘M’ to 1.
When we read a name, we identify the probable gender of that name by the sequence in which characters appear in that name. For example, “Stephen” is most likely a boy’s name but “Stephanie” is likely a girl’s name. To mimic the way we humans identify the gender of a name, we construct a simple Bidirectional LSTM model using the tensorflow.keras API.
Embedding layer: to “embed” each input character’s encoded number into a dense 256 dimension vector. The choice of embedding_dim is a hyperparameter that can be tuned to get the desired accuracy.Bidirectional LSTM layer: read the sequence of character embeddings from the previous step and output a single vector representing that sequence. The values for units and dropouts are hyperparameters as well.Final Dense layer: to output a single value close to 0 for ‘F’ or close to 1 for ‘M’ since this is the encoding we used in the preprocessing step.
Embedding layer: to “embed” each input character’s encoded number into a dense 256 dimension vector. The choice of embedding_dim is a hyperparameter that can be tuned to get the desired accuracy.
Bidirectional LSTM layer: read the sequence of character embeddings from the previous step and output a single vector representing that sequence. The values for units and dropouts are hyperparameters as well.
Final Dense layer: to output a single value close to 0 for ‘F’ or close to 1 for ‘M’ since this is the encoding we used in the preprocessing step.
We’ll use the standard tensorflow.keras training pipeline as below
Instantiate the model using the function we wrote in the model architecture step.Split the data into 80% training and 20% validation.Call model.fit with EarlyStopping callback to stop training once the model starts to overfit.Save the trained model to reuse while serving the web app.Plot the training and validation accuracies to visually check the model performance.
Instantiate the model using the function we wrote in the model architecture step.
Split the data into 80% training and 20% validation.
Call model.fit with EarlyStopping callback to stop training once the model starts to overfit.
Save the trained model to reuse while serving the web app.
Plot the training and validation accuracies to visually check the model performance.
Now that we have the trained model with good accuracy, we can create a Plotly Dash [Link] web app [https://www.boyorgirl.xyz] to get input names from a user, load the model (only once during app startup), use the model to predict the gender on the input names, and visualize the results back on the web app. The below code snippet only shows the model inference part of the web app. The full Plotly Dash web app code, including the model load, text box input, table output, and interactive bar plot output, is available on my GitHub repository.
The final step is to publish our new app on the internet for everyone worldwide to interact with. After a little bit of research, I decided to use Heroku to deploy the app for the following reasons.
Free!!!A straightforward deployment processMax 500MB memory is sufficient for my small custom model.
Free!!!
A straightforward deployment process
Max 500MB memory is sufficient for my small custom model.
The steps to deploy an app to Heroku are well documented on the Heroku website [Link]. I made custom changes to support my mono-repo format, which I’ve documented in my Github repo [Link]. The main changes to support mono-repos are
Add the following buildpack
heroku buildpacks:add -a <app> https://github.com/lstoll/heroku-buildpack-monorepo -i 1
Add the following configs
heroku config:set -a <app> PROCFILE=relative/path/to/app/Procfileheroku config:set -a <app> APP_BASE=relative/path/to/app
Important! One major gotcha that took me some time to figure out is that Heroku starts two workers by default. So if your app’s size is more than 250MB, the two workers combined would exceed the 500MB limit that Heroku sets for free apps. Since I don't expect the traffic to my app to be large enough to need two workers, I easily solved this issue by specifying only one worker by using the -w 1 flag in the Procfile.
web: gunicorn -w 1 serve:server
Free tier Heroku apps go to sleep after 30 mins of inactivity. Thus I used a free ping service called Kaffeine [Link] to ping my app once every 10mins. This will ensure zero downtime for the app.
Subsequently, I upgraded from Free tier to Hobby tier (mainly for Free SSL on my custom domain), ensuring the app never sleeps, so the ping service is no longer relevant for my app.
Finally, I purchased a cheap domain from Namecheap [Link] and pointed the domain to my Heroku app following instructions from here [Link].
On a serious note, we need to keep a few limitations and biases in mind while using this approach.
The model has ZERO understanding of the concept of gender in the real world! It is only making an informed guess at which gender a specific name probably belongs to based on historical data of names belonging to different genders. For example, my name begins with “Marie,” which the model detects as a female name (with the confidence of ~90%!) though I’m actually a male. Thus this approach perpetuates the inherent bias in our names, and it’s beyond the scope of this work to address these biases.The training data only consisted of binary genders (M and F). Thus, non-binary genders are not represented.
The model has ZERO understanding of the concept of gender in the real world! It is only making an informed guess at which gender a specific name probably belongs to based on historical data of names belonging to different genders. For example, my name begins with “Marie,” which the model detects as a female name (with the confidence of ~90%!) though I’m actually a male. Thus this approach perpetuates the inherent bias in our names, and it’s beyond the scope of this work to address these biases.
The training data only consisted of binary genders (M and F). Thus, non-binary genders are not represented.
In conclusion, please DO NOT use this app to make assumptions about anyone’s gender identity!
And that’s it! Our cool ML app to predict gender from names is now available for anyone on the internet to interact with! From my testing, the app seems to perform very well for English names and reasonably well for Indian names because of the names present in the training dataset. Non-English names like Chinese names performed poorly. Would you please take a look and let me know if it got your names correct? Thanks for reading!
All the code is available on my Github repo: [Link]
You can access “Boy Or Girl?” at: https://www.boyorgirl.xyz