Netflix Shows:
ML vs
Deep Learning
A complete walkthrough of the Netflix Shows dataset from Kaggle. Build 5 scikit-learn models and 2 TensorFlow neural networks to predict release year (regression) and classify Movie vs TV Show. Every line of code is explained for beginners — with copy buttons on every block.
# Netflix Shows — KaggleHub import kagglehub from kagglehub import KaggleDatasetAdapter df = kagglehub.load_dataset( KaggleDatasetAdapter.PANDAS, "shivamb/netflix-shows", file_path, ) print("First 5 records:", df.head())
Six steps from raw CSV
to model verdict.
The complete pipeline for the Netflix Shows machine learning project. Click any step to jump straight to its code and beginner-friendly explanation.
Data Loading with KaggleHub
Stream the Netflix Shows dataset (netflix_titles.csv) straight into a pandas DataFrame — ~8,800 rows × 12 columns including type, title, director, country, release_year, rating, duration, and genres.
Exploratory Data Analysis
Movie vs TV Show counts, top 10 countries, content rating distribution, release year trends, and top 10 genres on Netflix. Plus missing value analysis.
Preprocessing & Encoding
Fill missing values (director, cast, country), extract numeric duration from text (“90 min” → 90), label encode categorical features, create Movie vs TV Show target, scale features without leakage.
Machine Learning Models
Train Linear/Logistic Regression, Random Forest, Gradient Boosting, SVM and KNN — to predict release year (regression) and classify Movie vs TV Show (classification).
Deep Learning Models
Two 4-layer TensorFlow networks (128→64→32→1) with ReLU, BatchNorm, Dropout, EarlyStopping and ReduceLROnPlateau — one regression, one classification.
ML vs DL Comparison
Side-by-side leaderboard: R², RMSE, MAE for regression; accuracy, precision, recall, F1 for classification. The verdict on tree ensembles vs neural networks on entertainment data.
Load the dataset with KaggleHub.
Stream the Netflix Shows dataset straight into a pandas DataFrame — no manual download needed.
What is this dataset? The Netflix Shows dataset on Kaggle contains information about all movies and TV shows available on Netflix. Each row is one title, with columns for: show_id, type (Movie or TV Show), title, director, cast, country, date_added, release_year, rating, duration, listed_in (genres), and description. There are roughly 8,800 rows.
What is KaggleHub? Kaggle is a website where people share datasets for machine learning. KaggleHub is a Python library that lets you load those datasets directly into your code with one line — no manual downloading.
What is a DataFrame? A pandas DataFrame is like an Excel spreadsheet inside Python. It has rows (one per Netflix title) and columns (type, rating, duration, etc.). The variable df we create here holds all ~8,800 shows.
Why check shape, head(), info(), describe()?
df.shape→ How many rows (titles) and columns?df.head()→ Show the first 5 rows so you can see column names and sample valuesdf.info()→ What type of data is in each column? (text vs. numbers) How many missing values?df.describe()→ Basic statistics for numeric columns (like release_year)
Important: The file_path is the CSV filename inside the dataset. Visit the Kaggle dataset page → Files tab to find the exact filename. It’s typically "netflix_titles.csv".
# Install dependencies as needed:
# pip install kagglehub[pandas-datasets] pandas numpy matplotlib seaborn scikit-learn tensorflow
import kagglehub
from kagglehub import KaggleDatasetAdapter
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
# Set the path to the file you'd like to load
# Check the Kaggle dataset page → Files tab for the exact filename
file_path = "netflix_titles.csv" # ← replace with actual filename
# Load the latest version
df = kagglehub.load_dataset(
KaggleDatasetAdapter.PANDAS,
"shivamb/netflix-shows",
file_path,
)
print("Dataset shape:", df.shape)
print("First 5 records:")
print(df.head())
print(df.info())
print(df.describe())kagglehub loads the dataset, pandas handles data tables, numpy handles math, matplotlib and seaborn create charts."shivamb/netflix-shows", (3) load the file we specified. Result stored in df.(8870, 12) — 8,870 Netflix titles, 12 columns.object (text), only release_year is numeric (int64). Also shows missing values — director has ~2,600 NaNs, cast and country also have gaps.release_year: count, mean (~2014), std, min (1940s), max (2021). This tells us Netflix’s catalog spans 80+ years.Exploratory Data Analysis in seaborn.
Before any model touches the data, we visualize the type distribution, top countries, ratings, release year trends, and top genres.
What is EDA? Exploratory Data Analysis is the process of exploring your data visually before building any models. It’s like reading the show description before pressing play — you want to know what you’re working with.
What is a countplot? A countplot counts how many items fall into each category. For type, it shows how many Movies vs TV Shows Netflix has — typically about 70% movies, 30% TV shows.
What is a horizontal bar chart? For “top 10 countries,” a bar chart shows which countries produce the most Netflix content. The USA, India, and UK usually dominate.
What is a line chart for time trends? Plotting the number of shows released each year reveals Netflix’s explosive growth — content production skyrocketed after 2015.
Why does EDA matter? You’ll discover that the dataset is heavily skewed toward recent content, that most shows are movies, and that some columns (director, cast) have lots of missing values. This informs your preprocessing decisions.
2.1 · Missing values & dataset structure
# Check for missing values
print("Missing values:\n", df.isnull().sum())
print("\nDuplicates:", df.duplicated().sum())
categorical_cols = df.select_dtypes(include=['object']).columns
numeric_cols = df.select_dtypes(include=[np.number]).columns
print(f"\nCategorical columns: {list(categorical_cols)}")
print(f"Numeric columns: {list(numeric_cols)}")
print(df['type'].value_counts())
print(df['rating'].value_counts())director has ~2,600 missing values (30%!), cast ~825, country ~831. Only release_year is numeric. The type column has 2 values (Movie/TV Show), and rating has ~14 unique values (TV-MA, TV-14, R, PG-13, etc.).2.2 · Movies vs TV Shows & top countries
# Type distribution (Movie vs TV Show)
plt.figure(figsize=(8, 5))
sns.countplot(data=df, x='type', palette=['#e50914', '#221f1f'])
plt.title('Movies vs TV Shows on Netflix')
plt.show()
# Top 10 countries
top_countries = df['country'].value_counts().head(10)
plt.figure(figsize=(12, 6))
top_countries.plot(kind='barh', color='#e50914')
plt.title('Top 10 Countries by Number of Shows')
plt.xlabel('Number of Shows')
plt.tight_layout()
plt.show()The countplot shows Netflix is ~70% movies, ~30% TV shows. The top countries chart reveals United States, India, and United Kingdom as the biggest content producers — with the US dominating by a wide margin.
2.3 · Rating distribution & release year trends
# Rating distribution
plt.figure(figsize=(12, 5))
df['rating'].value_counts().plot(kind='bar', color='#831010')
plt.title('Distribution of Content Ratings')
plt.xticks(rotation=45)
plt.tight_layout()
plt.show()
# Release year trends
plt.figure(figsize=(14, 5))
df.groupby('release_year').size().plot(
kind='line', color='#e50914', linewidth=2)
plt.title('Number of Shows Released per Year')
plt.xlabel('Release Year')
plt.ylabel('Count')
plt.tight_layout()
plt.show()The rating distribution shows TV-MA (mature audiences) and TV-14 as the most common ratings. The release year line chart reveals Netflix’s explosive growth after 2015 — content production skyrocketed as Netflix shifted from licensing to original content.
2.4 · Top 10 genres
# Top genres (from listed_in column — comma-separated)
all_genres = df['listed_in'].str.split(',').explode().str.strip()
top_genres = all_genres.value_counts().head(10)
plt.figure(figsize=(12, 6))
top_genres.plot(kind='barh', color='#e50914')
plt.title('Top 10 Genres on Netflix')
plt.tight_layout()
plt.show()listed_in column contains comma-separated genres. Using str.split(',').explode() splits each show’s genres into separate rows, so we can count individual genres. Dramas, Comedies, and Documentaries typically dominate.Encode, engineer, scale — without leakage.
The Netflix dataset has missing values in director/cast/country, text-based duration (“90 min”), and mostly categorical features. We handle all of this here.
Why do we need preprocessing? Machine learning models only understand numbers. Our dataset has columns like "United States" and "TV-MA" — we need to convert these to numbers before any model can use them.
Handling missing values: The Netflix dataset has many missing values in director (~2,600), cast (~825), and country (~831). We fill them with the string "Unknown" — this is better than dropping rows because we keep all ~8,800 titles.
Extracting numeric duration: The duration column contains text like "90 min" or "3 seasons". We use a regular expression str.extract(r'(\d+)') to pull out just the number (90 or 3) into a new numeric column called duration_num.
Label encoding for categorical features: We use LabelEncoder to convert text columns (type, country, rating, listed_in) into numbers. Example: Movie=0, TV Show=1, United States=200, India=100, etc.
What is a target variable? For regression, the target is release_year (a continuous number). For classification, the target is is_movie — 1 if the title is a Movie, 0 if it’s a TV Show.
What is train/test split? We divide data into 80% for training and 20% for testing. random_state=42 makes the split reproducible.
What is scaling? Standardization rescales every feature so mean=0, std=1. This matters because models like SVM and KNN compare distances — without scaling, features with larger ranges would dominate.
What is data leakage? When information from the test set accidentally influences training. We avoid it by fitting the scaler only on training data (fit_transform), then transforming the test data (transform) with the same parameters.
from sklearn.preprocessing import LabelEncoder, StandardScaler
from sklearn.model_selection import train_test_split
data = df.copy()
# 3.1 Fill missing values
for col in ['director', 'cast', 'country']:
data[col] = data[col].fillna('Unknown')
data['rating'] = data['rating'].fillna(data['rating'].mode()[0])
# 3.2 Extract numeric duration from text ("90 min" → 90, "3 seasons" → 3)
data['duration_num'] = data['duration'].str.extract(r'(\d+)').astype(float)
data['duration_num'] = data['duration_num'].fillna(data['duration_num'].median())
# 3.3 Label encode categorical features
le = LabelEncoder()
for col in ['type', 'country', 'rating', 'listed_in']:
data[col + '_enc'] = le.fit_transform(data[col].astype(str))
# 3.4 Create classification target: Movie (1) vs TV Show (0)
data['is_movie'] = (data['type'] == 'Movie').astype(int)
# 3.5 Define features and targets
feature_cols = ['duration_num', 'country_enc',
'rating_enc', 'listed_in_enc', 'is_movie']
X_reg = data[feature_cols]
y_reg = data['release_year']
X_clf = data[feature_cols]
y_clf = data['is_movie']
# 3.6 Train/test split (80/20)
X_reg_train, X_reg_test, y_reg_train, y_reg_test = train_test_split(
X_reg, y_reg, test_size=0.2, random_state=42)
X_clf_train, X_clf_test, y_clf_train, y_clf_test = train_test_split(
X_clf, y_clf, test_size=0.2, random_state=42)
# 3.7 Feature scaling (no leakage)
scaler_reg = StandardScaler()
X_reg_train_scaled = scaler_reg.fit_transform(X_reg_train)
X_reg_test_scaled = scaler_reg.transform(X_reg_test)
scaler_clf = StandardScaler()
X_clf_train_scaled = scaler_clf.fit_transform(X_clf_train)
X_clf_test_scaled = scaler_clf.transform(X_clf_test)
print(f"Train shape: {X_reg_train.shape}, Test shape: {X_reg_test.shape}")
print(f"Class distribution:\n{y_clf.value_counts(normalize=True)}")director, cast, country with the string "Unknown". For rating, fill with the mode (most common value). This keeps all ~8,800 rows instead of dropping 30%.duration column has text like "90 min" or "3 Seasons". The regex r'(\d+)' extracts just the number → 90 or 3. Store as duration_num (numeric). Fill any remaining NaN with the median.type, country, rating, and listed_in — converts text to numbers. We create new _enc columns to keep the originals.duration_num, country_enc, rating_enc, listed_in_enc, and is_movie. For regression (predict release_year), we use all 5. For classification (predict is_movie), we drop is_movie from X to avoid leaking the answer — but note: since duration contains “min” vs “seasons”, the model may learn this pattern easily.random_state=42 = reproducible.fit_transform on train (learns mean/std), transform on test (applies same parameters). No data leakage.Five scikit-learn models,
two tasks.
For each task — predict release year (regression) and classify Movie vs TV Show (classification) — we train five models.
What is supervised learning? Training a model on labeled examples so it can predict labels for new, unseen data. Two types:
- Regression: predict a continuous number — e.g., “this show was released in 2018”
- Classification: predict a category — e.g., “this title is a Movie (1) or TV Show (0)”
The five models, explained simply:
- Linear Regression: draws the best-fitting straight line through the data. Simple, fast baseline.
- Logistic Regression: for classification — estimates the probability of being a Movie vs TV Show.
- Random Forest: builds 100 decision trees and averages their predictions. “Wisdom of the crowd.”
- Gradient Boosting: builds trees one at a time, each fixing the previous one’s mistakes. Often the strongest on tabular data.
- SVM: finds the best boundary between classes. Good for small datasets, sensitive to scaling.
- KNN: for a new title, finds the 5 most similar titles and averages their values. Simple but scaling-sensitive.
Regression metrics:
- RMSE: “off by X years on average.”
- R²: variance explained. 1.0 is perfect, 0 = no better than guessing the mean.
Classification metrics:
- Accuracy: fraction of all predictions that were correct.
- Precision: of all predicted “Movies,” how many actually were?
- Recall: of all actual “Movies,” how many did we catch?
- F1: harmonic mean of precision and recall. Balanced score.
4.1 · Regression — Predict Release Year
from sklearn.linear_model import LinearRegression
from sklearn.ensemble import RandomForestRegressor, GradientBoostingRegressor
from sklearn.svm import SVR
from sklearn.neighbors import KNeighborsRegressor
from sklearn.metrics import mean_squared_error, mean_absolute_error, r2_score
reg_models = {
'Linear Regression': LinearRegression(),
'Random Forest': RandomForestRegressor(n_estimators=100, random_state=42),
'Gradient Boosting': GradientBoostingRegressor(n_estimators=100, random_state=42),
'Support Vector Regressor': SVR(kernel='rbf', C=1.0),
'K-Nearest Neighbors': KNeighborsRegressor(n_neighbors=5),
}
reg_results = []
for name, model in reg_models.items():
model.fit(X_reg_train_scaled, y_reg_train)
y_pred = model.predict(X_reg_test_scaled)
mse = mean_squared_error(y_reg_test, y_pred)
rmse = np.sqrt(mse)
mae = mean_absolute_error(y_reg_test, y_pred)
r2 = r2_score(y_reg_test, y_pred)
reg_results.append({
'Model': name, 'MSE': round(mse, 2),
'RMSE': round(rmse, 2), 'MAE': round(mae, 2),
'R²': round(r2, 4)
})
reg_results_df = pd.DataFrame(reg_results).sort_values('R²', ascending=False)
print(reg_results_df.to_string(index=False))4.2 · Classification — Predict Movie vs TV Show
from sklearn.linear_model import LogisticRegression
from sklearn.ensemble import RandomForestClassifier, GradientBoostingClassifier
from sklearn.svm import SVC
from sklearn.neighbors import KNeighborsClassifier
from sklearn.metrics import accuracy_score, precision_score, recall_score, f1_score, confusion_matrix, classification_report
clf_models = {
'Logistic Regression': LogisticRegression(random_state=42, max_iter=1000),
'Random Forest': RandomForestClassifier(n_estimators=100, random_state=42),
'Gradient Boosting': GradientBoostingClassifier(n_estimators=100, random_state=42),
'Support Vector Classifier': SVC(kernel='rbf', random_state=42, probability=True),
'K-Nearest Neighbors': KNeighborsClassifier(n_neighbors=5),
}
clf_results = []
for name, model in clf_models.items():
model.fit(X_clf_train_scaled, y_clf_train)
y_pred = model.predict(X_clf_test_scaled)
clf_results.append({
'Model': name,
'Accuracy': round(accuracy_score(y_clf_test, y_pred), 4),
'Precision': round(precision_score(y_clf_test, y_pred), 4),
'Recall': round(recall_score(y_clf_test, y_pred), 4),
'F1 Score': round(f1_score(y_clf_test, y_pred), 4),
})
clf_results_df = pd.DataFrame(clf_results).sort_values('Accuracy', ascending=False)
print(clf_results_df.to_string(index=False))
# Confusion matrix for best model
best_clf = clf_models[clf_results_df.iloc[0]['Model']]
y_pred_best = best_clf.predict(X_clf_test_scaled)
cm = confusion_matrix(y_clf_test, y_pred_best)
sns.heatmap(cm, annot=True, fmt='d', cmap='Blues',
xticklabels=['TV Show', 'Movie'], yticklabels=['TV Show', 'Movie'])
plt.show()duration_num is in the features (movies have “min”, TV shows have “seasons”), the model can learn this pattern easily — expect high accuracy. To make the task harder, try removing duration_num from feature_cols and see how accuracy changes.Two TensorFlow neural networks
with modern regularization.
Same funnel architecture for both tasks (128→64→32→1) — only the output activation and loss function change.
What is a neural network? A stack of layers, each containing “neurons” (math units). Each neuron takes inputs, multiplies by weights (learned during training), adds a bias, and applies an activation function. “Deep” = many layers.
The architecture, explained:
Dense(128): 128 neurons, each connected to every neuron in the previous layer. First layer takes our 5 features.Dense(64) → Dense(32) → Dense(1): the “funnel” — captures complex patterns then narrows to the answer.ReLU: if input is negative, output 0; if positive, output as-is. Lets the network learn non-linear patterns.
Regularization — preventing overfitting:
BatchNormalization: normalizes layer outputs during training. Stabilizes learning.Dropout(0.3): randomly disables 30% of neurons each step. Forces the network to learn redundant representations.
Training configuration:
Adam: adjusts learning rate automatically. The default choice for most projects.MSE loss(regression): penalizes large errors more than small ones.Binary crossentropy(classification): standard loss for yes/no problems (Movie vs TV Show).Epoch: one full pass through training data. We train for up to 200.Batch size (32): process 32 titles at a time before updating weights.Validation split (0.2): 20% of training data held out to monitor overfitting.
Callbacks — automatic training controls:
EarlyStopping: if val loss doesn’t improve for 20 epochs, stop.restore_best_weights=Truerolls back to the best epoch.ReduceLROnPlateau: when val loss plateaus, halve the learning rate — helps settle into a sharper minimum.
Regression vs classification — the only difference:
- Regression: final layer = LINEAR activation (outputs any number — the predicted release year).
- Classification: final layer = SIGMOID activation (outputs 0–1 = probability of “Movie”). Threshold at 0.5.
5.1 · DL Regression — Predict Release Year
import tensorflow as tf
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Dense, Dropout, BatchNormalization
from tensorflow.keras.callbacks import EarlyStopping, ReduceLROnPlateau
tf.random.set_seed(42)
np.random.seed(42)
def build_regression_model(input_dim):
model = Sequential([
Dense(128, activation='relu', input_shape=(input_dim,)),
BatchNormalization(),
Dropout(0.3),
Dense(64, activation='relu'),
BatchNormalization(),
Dropout(0.2),
Dense(32, activation='relu'),
Dropout(0.1),
Dense(1, activation='linear')
])
model.compile(optimizer='adam', loss='mse', metrics=['mae'])
return model
dl_reg_model = build_regression_model(X_reg_train_scaled.shape[1])
early_stop = EarlyStopping(monitor='val_loss', patience=20,
restore_best_weights=True, verbose=1)
reduce_lr = ReduceLROnPlateau(monitor='val_loss', factor=0.5,
patience=10, min_lr=1e-6, verbose=1)
history_reg = dl_reg_model.fit(
X_reg_train_scaled, y_reg_train,
validation_split=0.2, epochs=200, batch_size=32,
callbacks=[early_stop, reduce_lr], verbose=1
)
dl_reg_pred = dl_reg_model.predict(X_reg_test_scaled).flatten()
dl_reg_rmse = np.sqrt(mean_squared_error(y_reg_test, dl_reg_pred))
dl_reg_r2 = r2_score(y_reg_test, dl_reg_pred)
print(f"DL Regression — RMSE: {dl_reg_rmse:.2f}, R²: {dl_reg_r2:.4f}")5.2 · DL Classification — Predict Movie vs TV Show
tf.random.set_seed(42)
np.random.seed(42)
def build_classification_model(input_dim):
model = Sequential([
Dense(128, activation='relu', input_shape=(input_dim,)),
BatchNormalization(),
Dropout(0.3),
Dense(64, activation='relu'),
BatchNormalization(),
Dropout(0.2),
Dense(32, activation='relu'),
Dropout(0.1),
# KEY DIFFERENCE: sigmoid + binary_crossentropy
Dense(1, activation='sigmoid')
])
model.compile(optimizer='adam',
loss='binary_crossentropy',
metrics=['accuracy'])
return model
dl_clf_model = build_classification_model(X_clf_train_scaled.shape[1])
early_stop_clf = EarlyStopping(monitor='val_loss', patience=20,
restore_best_weights=True, verbose=1)
reduce_lr_clf = ReduceLROnPlateau(monitor='val_loss', factor=0.5,
patience=10, min_lr=1e-6, verbose=1)
history_clf = dl_clf_model.fit(
X_clf_train_scaled, y_clf_train,
validation_split=0.2, epochs=200, batch_size=32,
callbacks=[early_stop_clf, reduce_lr_clf], verbose=1
)
dl_clf_prob = dl_clf_model.predict(X_clf_test_scaled).flatten()
# Threshold at 0.5: probability >= 0.5 → Movie (1), else TV Show (0)
dl_clf_pred = (dl_clf_prob >= 0.5).astype(int)
dl_clf_acc = accuracy_score(y_clf_test, dl_clf_pred)
dl_clf_f1 = f1_score(y_clf_test, dl_clf_pred)
print(f"DL Classification — Accuracy: {dl_clf_acc:.4f}, F1: {dl_clf_f1:.4f}")The final leaderboard.
Concatenate the ML results with the DL metrics and sort.
How to read the results table:
- For regression: higher R² is better. Lower RMSE is better (in years — RMSE of 8 means “off by ~8 years on average”).
- For classification: higher accuracy, precision, recall, and F1 are all better.
The pattern you’ll see: On this Netflix dataset, Gradient Boosting and Random Forest typically match or beat the neural network. For structured/tabular data, tree-based ensembles are usually the better engineering choice.
Key lesson: Always start with simple models as baselines. Move to tree-based ensembles for tabular data. Reach for deep learning when data is large or unstructured.
# Regression comparison
combined_reg = pd.concat([reg_results_df, pd.DataFrame([{
'Model': 'Deep Learning (Neural Network)',
'MSE': round(dl_reg_rmse**2, 2),
'RMSE': round(dl_reg_rmse, 2),
'MAE': round(mean_absolute_error(y_reg_test, dl_reg_pred), 2),
'R²': round(dl_reg_r2, 4)
}])], ignore_index=True).sort_values('R²', ascending=False)
print(combined_reg.to_string(index=False))
# Classification comparison
combined_clf = pd.concat([clf_results_df, pd.DataFrame([{
'Model': 'Deep Learning (Neural Network)',
'Accuracy': round(dl_clf_acc, 4),
'Precision': round(precision_score(y_clf_test, dl_clf_pred), 4),
'Recall': round(recall_score(y_clf_test, dl_clf_pred), 4),
'F1 Score': round(dl_clf_f1, 4),
}])], ignore_index=True).sort_values('Accuracy', ascending=False)
print(combined_clf.to_string(index=False))What the project
actually tells us.
Six findings from running the full pipeline on the Netflix Shows dataset.
// ~70% movies · USA dominates · post-2015 explosionNetflix is ~70% movies, ~30% TV shows
The countplot clearly shows the imbalance. This matters for classification — a model that always predicts “Movie” would be 70% accurate without learning anything.
United States dominates content production
The top-10 countries bar chart shows the US produces far more Netflix content than any other country, followed by India and the UK.
Content production exploded after 2015
The release year line chart reveals Netflix’s shift from licensing to original content. The number of titles released per year skyrocketed after 2015.
Tree ensembles match or beat DL on Netflix data
Gradient Boosting and Random Forest typically outperform the neural network on this structured dataset. Deep learning isn’t always the answer — for tabular data, tree-based ensembles win.
Duration is a strong predictor of type
Movies have “min” in their duration, TV shows have “seasons.” This makes the Movie vs TV Show classification task relatively easy — try removing duration_num from features to make it harder.
Preprocessing matters more than architecture
Handling missing values, extracting numeric duration from text, and encoding categorical features correctly usually move the needle more than swapping model architectures.
Frequently Asked Questions
What is the Netflix Shows dataset? +
The Netflix Shows dataset on Kaggle contains information about all movies and TV shows available on Netflix — ~8,800 titles with 12 columns including type, title, director, cast, country, release year, rating, duration, and genres.
Which ML algorithm is best for Netflix data? +
For this dataset, Gradient Boosting and Random Forest typically perform at the top. Tree-based ensembles handle mixed feature types, capture non-linear interactions, and resist overfitting on structured entertainment data.
Is deep learning better than ML for Netflix data? +
Not necessarily. On this ~8,800-row dataset, traditional ML models matched or outperformed a 4-layer neural network. Deep learning tends to pull ahead on very large datasets or unstructured inputs (images, text, audio).
Why does the Movie vs TV Show classification get high accuracy? +
Because the duration column contains “min” for movies and “seasons” for TV shows — the model can easily learn this pattern. To make the task harder, remove duration_num from feature_cols and see how accuracy changes.
Run the project
yourself.
Grab the Netflix Shows dataset from Kaggle, install the stack with one pip command, and run every cell end-to-end. Or click “Copy Full Project Code” at the top of this page.
