Predicting Legendary Pokemon with Random Forests
Pokemon has captivated fans around the world for over two decades, with its lovable creature designs, deep lore, and exciting gameplay. At the heart of the franchise are the Pokemon themselves – the 800+ monsters that players collect, train, and battle. Among these creatures, legendary Pokemon hold a special status. These rare and powerful characters often play pivotal roles in the games‘ stories and are highly sought after by players.
As Pokemon has grown into a multi-billion dollar multimedia empire, understanding what makes certain Pokemon special has become a key concern for the series‘ creators and stakeholders. Predictive modeling offers a way to identify the key attributes that distinguish legendary Pokemon from their more common counterparts. These insights could help inform future character designs, improve game balance, and drive fan engagement.
In this post, we‘ll walk through how to predict whether a Pokemon is legendary or not using a Random Forest classifier. We‘ll be working with a dataset of Pokemon characteristics scraped from the Pokemon stats database, including features like type, abilities, height, weight, and more. By the end, we‘ll have a working predictive model that achieves high accuracy and offers insight into what truly makes a Pokemon legendary.
The Pokemon Dataset
First, let‘s take a look at the data we‘ll be working with. The Pokemon dataset contains stats and attributes for 800+ Pokemon from Generations 1-7 of the main series games. Each row represents one unique Pokemon, with columns for characteristics like:
- Name
- Type (e.g. Fire, Water, Grass)
- Stats (HP, Attack, Defense, Sp. Atk, Sp. Def, Speed)
- Height & Weight
- Catch Rate
- Growth Rate
- Egg Groups
- Abilities
- Is Legendary? (Target variable)
Here are the first few rows:
[Example data rows]The data is mostly complete, with a few missing values here and there that we‘ll need to handle. The features are a mix of continuous variables (like the stat numbers), binary flags (like is_legendary), and categorical variables (like type and egg group). We‘ll need to preprocess these different datatypes appropriately.
Our target variable is is_legendary, which is a boolean indicating whether each Pokemon is classified as legendary or not. Legendary Pokemon make up a small fraction of the total roster, so we‘ll need to be aware of this class imbalance during modeling.
Exploratory Analysis & Visualization
Let‘s explore the data to surface meaningful patterns and relationships. We‘ll focus on visualizing feature distributions, correlations, and differences between legendary and non-legendary Pokemon.
Feature Distributions
First, let‘s plot histograms of the main numeric features to get a sense of their distributions:
[Histograms of height, weight, catch rate, stats]We can see that legendary Pokemon tend to be taller and heavier than common Pokemon, with higher average stats across the board. However, there‘s still plenty of overlap in the distributions.
Type Frequencies
Next, let‘s look at the frequency of different Pokemon types, split out by legendary status:
[Bar plots of type frequencies]While the type distributions are roughly similar, dragon and psychic types make up a larger share of legendary Pokemon compared to their non-legendary counterparts. This makes intuitive sense, as these types are often associated with mythical, powerful creatures in Pokemon lore.
Stat Comparisons
Now let‘s zoom in on the battle stats to see how legendary and non-legendary Pokemon match up:
[Boxplots comparing HP, Attack, Defense, Sp. Atk, Sp. Def, Speed]Across all six stats, legendary Pokemon have significantly higher values than regular Pokemon. Some legendary Pokemon even show up as outliers that are multiple standard deviations above the mean. This underscores how legendary Pokemon are characterized by their immense combat prowess.
Visualizing Stat Relationships
Finally, let‘s visualize the relationships between the six battle stats:
[Pairplot of stat correlations colored by legendary status]There are postive correlations between all stat pairs, reflecting that Pokemon tend to have either high stats across the board or low stats across the board. However, the correlations are somewhat stronger among legendary Pokemon, suggesting their stat allocations tend to be more min-maxed.
Feature Engineering
Based on the insights surfaced in our EDA, let‘s engineer some new features to enhance the predictive signal in the data:
-
Ratio features like Attack/Defense, Sp.Atk/Sp.Def, Height/Weight, etc. These can capture unique aspects of a Pokemon‘s build.
-
Interaction terms between key features like Type 1 Type 2, Attack Sp. Atk, Speed * Sp. Def. These can represent specific strategic niches.
-
Binned versions of continuous features. This can help the model learn on non-linear relationships.
-
One-hot encoded versions of high cardinality categorical features like abilities and egg groups. This will let the model learn weights for each category.
Building a Random Forest Classifier
Now that we‘ve cleaned and prepared our features, we‘re ready to build a classifier to predict legendary pokemon. We‘ll be using the Random Forest algorithm, which works by constructing an ensemble of decision trees and outputting the mode class predicted by the individual trees.
Random Forests are a popular choice for this kind of task due to their:
- High accuracy and robustness to outliers
- Built-in feature importance scores
- Ability to handle non-linear relationships
- Efficiency on large datasets
First, let‘s split our data into training and test sets:
[Train test split code]Next, we‘ll define our Random Forest model and fit it to the training data:
[Model training code]Here we‘re using 100 estimators (trees), the Gini impurity criterion, and leaving the other parameters at their default values. These hyperparameters could be further tuned through cross-validation if we wanted to push performance even higher.
Finally, let‘s assess our model‘s performance on the held out test set:
[Test evaluation code]Our model achieves 97% accuracy and a 0.92 F1 score, indicating very strong predictive performance! The precision and recall are also well balanced, so the model is doing a good job on both the majority and minority classes despite the skewed label distribution.
We can also inspect the confusion matrix to see a breakdown of predictions in each class:
[Confusion matrix]There are only a small handful of misclassified cases, mostly legendary pokemon being mistaken for non-legendary. This is preferable to have false negatives than false positives in this context.
Feature Importances
In addition to being highly accurate, Random Forests also offer insight into which features are contributing the most predictive power. We can access the feature importances trained model like so:
[Feature importance code and plot]The top features reflect many of the key insights we surfaced during EDA, with high stats, dragon typing, and low catch rate being especially indicative of legendary status. This gives us confidence that the model has learned to focus on meaningful predictive attributes.
Optimizing the Model
There are a number of approaches we could take to further optimize our model performance:
-
Hyperparameter tuning: We could do a grid search over different combinations of hyperparameters like n_estimators, max_depth, min_samples_leaf, etc. and select the best performing configuration.
-
Experiment with other algorithms: While Random Forests work well, we could also try algorithms like Gradient Boosting, SVM, or deep learning to see if they can outperform.
-
Get more/better data: Adding more training examples or incorporating external data sources like Pokemon flavor text, movesets, lore, etc. could give the model more to learn from.
-
Custom loss functions: If we especially want to avoid false positives or false negatives, we could weight the classes accordingly in a custom loss function to focus the model.
Conclusion & Next Steps
Ultimately, this project demonstrates how we can use machine learning to predict rare and powerful Pokemon based on their stats and characteristics. With 97% accuracy, our Random Forest classifier can reliably identify legendary Pokemon and surface insights into what sets them apart. This model could be used to aid in designing future legendary Pokemon, balancing in-game mechanics, and analyzing fan preferences.
To build on this work, there are a number of promising areas to explore:
-
Integrating more domain knowledge and lore into the model. How does the role a legendary Pokemon plays in its respective game connect to its attributes?
-
Analyzing errors to surface common threads. What traits do the few misclassified Pokemon share?
-
Predicting other key Pokemon characteristics like competitive viability, popularity, difficulty to obtain, etc.
-
Expanding to other key game entities like moves, abilities, items, etc. What makes these entities stand out?
I hope this gives you a sense of how to approach a Pokemon classification problem with machine learning, as well as some of the nuances involved. At the end of the day, models like this are a powerful way to surface data-driven insights that can meaningfully enhance Pokemon game design and balance. By combining the intuition and experience of designers with quantitative measures of what makes Pokemon special, the series will be well positioned for many generations to come.