Look for the interactive boxes: Ask the Audience (Section 01), One Tree vs a Forest (03), Bootstrap Sampler (04), More Trees & the OOB Score (08), MDI vs Permutation Importance (09), max_features & Tree Correlation (10) and Imbalanced Classes (12). Every forest in them is trained live in your browser.
The Story That Explains Random Forest
The audience usually wins. No single person in it is smarter than your friend. But each person makes different mistakes, and when 500 people vote, those mistakes go in all directions and cancel out. Your friend has only one brain — one blind spot can cost you everything.
That is the whole idea behind Random Forest.
A Random Forest is a team of many decision trees. Each tree learns from a slightly different random sample of the data, and each split looks at only a random few features. To predict, every tree gives an answer. For classification the majority vote wins. For regression the answers are averaged. No tree has to be perfect — the team is strong because the trees make different mistakes.
Train many models that are decent and different, then combine their answers. The combined answer is usually more accurate and more stable than any single model. This is called ensemble learning, and Random Forest is one of its most reliable forms. There is one condition: the models must not all make the same mistakes.
Try It — Ask the Audience
Each voter is right only 60% of the time. Add more voters and watch the majority become almost always right. Then raise ρ (how alike the voters think) and see the magic disappear.
इन interactive boxes को देखिए: Ask the Audience (सेक्शन 01), One Tree vs a Forest (03), Bootstrap Sampler (04), More Trees & the OOB Score (08), MDI vs Permutation Importance (09), max_features & Tree Correlation (10) और Imbalanced Classes (12)। इनका हर forest आपके browser में live train होता है।
वह कहानी जो Random Forest को समझाती है
आमतौर पर audience जीतती है। उसमें कोई भी अकेला इंसान आपके दोस्त से ज़्यादा समझदार नहीं है। पर हर इंसान अलग-अलग ग़लतियाँ करता है, और जब 500 लोग vote करते हैं, तो वे ग़लतियाँ हर दिशा में जाती हैं और एक-दूसरे को काट देती हैं। आपके दोस्त के पास सिर्फ़ एक दिमाग़ है — एक कमज़ोर कड़ी आपका सब कुछ छीन सकती है।
Random Forest के पीछे पूरा idea यही है।
Random Forest बहुत सारे decision trees की एक team है। हर tree data के एक थोड़े अलग random sample से सीखता है, और हर split सिर्फ़ कुछ random features को देखता है। Predict करने के लिए हर tree एक जवाब देता है। Classification में majority vote जीतता है। Regression में जवाबों का average लिया जाता है। किसी tree को perfect होने की ज़रूरत नहीं — team इसलिए मज़बूत है क्योंकि trees अलग-अलग ग़लतियाँ करते हैं।
ऐसे बहुत सारे models train कीजिए जो ठीक-ठाक और अलग-अलग हों, फिर उनके जवाबों को मिलाइए। मिला हुआ जवाब आमतौर पर किसी भी अकेले model से ज़्यादा सटीक और ज़्यादा stable होता है। इसे ensemble learning कहते हैं, और Random Forest इसके सबसे भरोसेमंद रूपों में से एक है। एक शर्त है: सारे models एक जैसी ग़लतियाँ नहीं करने चाहिए।
ख़ुद आज़माइए — Ask the Audience
हर voter सिर्फ़ 60% बार सही होता है। और voters जोड़िए और देखिए कि majority लगभग हमेशा सही होने लगती है। फिर ρ बढ़ाइए (voters कितना एक जैसा सोचते हैं) और देखिए कि जादू ग़ायब हो जाता है।
请留意这些可以互动的方框:Ask the Audience(第 01 节)、One Tree vs a Forest(03)、Bootstrap Sampler(04)、More Trees & the OOB Score(08)、MDI vs Permutation Importance(09)、max_features & Tree Correlation(10)和 Imbalanced Classes(12)。里面的每一片 forest 都是在你的浏览器里实时训练的。
一个能解释 Random Forest 的故事
通常观众会赢。观众里没有一个人比你的朋友更聪明。但每个人犯的错误都不一样, 当 500 个人一起投票时,这些错误朝着各个方向,互相抵消了。你的朋友只有一个大脑 —— 一个盲点就可能让你输掉一切。
这就是 Random Forest 背后的全部想法。
Random Forest 是由很多棵 decision tree 组成的一个团队。每棵 tree 从数据中一个稍有不同的随机 sample 里学习, 而且每次 split 只看随机选出的几个 feature。做预测时,每棵 tree 都给出一个答案。 对于 classification,majority vote 胜出。对于 regression,把答案取平均。 没有哪棵 tree 需要完美 —— 这个团队之所以强,是因为每棵 tree 犯的错误不一样。
训练很多个还不错、又各不相同的 model,然后把它们的答案合起来。 合起来的答案通常比任何一个单独的 model 更准、更稳定。 这叫做 ensemble learning,Random Forest 是其中最可靠的形式之一。 只有一个条件:这些 model 不能都犯同样的错误。
动手试试 —— Ask the Audience
每个投票者只有 60% 的时候是对的。增加投票者,看 majority 变得几乎总是对的。然后调高 ρ(投票者的想法有多相似),看魔法消失。
The Foundation — Decision Trees (Quick Recap)
Before building a forest, we need one tree. A decision tree splits the data by asking yes/no questions, one feature at a time, until it reaches a prediction.
A deep tree keeps splitting until every leaf is pure. So it memorises the training data — the noise, the outliers, even one strange row. Training accuracy is close to 100%, but accuracy on new data is much lower. This is overfitting. Worse, a small change in the data can give a completely different tree. We say the tree has high variance.
The Two Ingredients of Random Forest
Random Forest fixes the variance problem by adding randomness in two separate ways. Both make the trees different from each other.
max_features).
scikit-learn default: √p for classification and all p (1.0) for regression.
Many people use p/3 for regression, but you must set it yourself.
With bagging alone, every tree can still use every feature. One strong feature then wins the first split in almost every tree, so the trees look alike. With feature randomness alone, every tree sees the same rows. Together they give truly different trees, whose mistakes cancel instead of adding up.
Try It — One Tree vs a Forest
Start with 1 tree and look at its jagged border. Then use 200 trees. Click on the map to see how the trees vote for one point. Untick both boxes to see what happens with no randomness.
नींव — Decision Trees (जल्दी से दोहराएँ)
Forest बनाने से पहले हमें एक tree चाहिए। Decision tree हाँ/ना वाले सवाल पूछकर data को split करता है, एक बार में एक feature, जब तक वह किसी prediction तक नहीं पहुँचता।
गहरा tree तब तक split करता रहता है जब तक हर leaf pure न हो जाए। इसलिए वह training data को रट लेता है — noise, outliers, यहाँ तक कि एक अजीब row भी। Training accuracy लगभग 100% होती है, पर नए data पर accuracy बहुत कम होती है। यही overfitting है। इससे भी बुरा, data में छोटा-सा बदलाव बिल्कुल अलग tree दे सकता है। हम कहते हैं कि tree का variance high है।
Random Forest की दो सामग्रियाँ
Random Forest variance की समस्या को दो अलग तरीक़ों से randomness जोड़कर ठीक करता है। दोनों तरीक़े trees को एक-दूसरे से अलग बनाते हैं।
max_features) देख सकता है।
scikit-learn का default: classification के लिए √p और regression के लिए all p (1.0)।
बहुत लोग regression के लिए p/3 इस्तेमाल करते हैं, पर इसे आपको ख़ुद set करना होगा।
सिर्फ़ bagging हो, तो हर tree फिर भी हर feature इस्तेमाल कर सकता है। तब एक मज़बूत feature लगभग हर tree में पहला split जीत लेता है, और trees एक जैसे दिखते हैं। सिर्फ़ feature randomness हो, तो हर tree वही rows देखता है। दोनों साथ मिलकर सच में अलग trees देते हैं, जिनकी ग़लतियाँ जुड़ने के बजाय कट जाती हैं।
ख़ुद आज़माइए — One Tree vs a Forest
1 tree से शुरू कीजिए और उसकी टेढ़ी-मेढ़ी border देखिए। फिर 200 trees लीजिए। Map पर click करके देखिए कि trees एक point के लिए कैसे vote करते हैं। दोनों boxes untick कीजिए और देखिए कि बिना randomness के क्या होता है।
基础 —— Decision Tree(快速复习)
在建一片 forest 之前,我们需要先有一棵 tree。decision tree 通过问“是 / 否”问题来 split 数据,一次看一个 feature,直到得出一个预测。
一棵很深的 tree 会一直 split,直到每个 leaf 都是纯的。所以它会死记 training data —— 噪声、outlier,甚至一行奇怪的数据都记住。 training accuracy 接近 100%,但在新数据上的 accuracy 低得多。 这就是 overfitting。更糟的是,数据有一点小变化,就可能得到一棵完全不同的 tree。我们说这棵 tree 有 high variance。
Random Forest 的两种原料
Random Forest 用两种不同的方式加入随机性,来解决 variance 的问题。两种方式都让 tree 彼此不同。
max_features)。
scikit-learn 的默认值:classification 用 √p,regression 用 全部 p(1.0)。
很多人在 regression 中用 p/3,但你必须自己设置。
只用 bagging 时,每棵 tree 仍然可以用所有 feature。这样一个很强的 feature 几乎会在每棵 tree 的第一次 split 中胜出,所以各棵 tree 看起来都差不多。 只用 feature 随机性时,每棵 tree 看到的都是同样的行。两者一起,才能得到真正不同的 tree,它们的错误会互相抵消,而不是累加起来。
动手试试 —— One Tree vs a Forest
先用 1 棵 tree,看看它锯齿状的边界。然后用 200 棵 tree。点击地图,看各棵 tree 如何为一个点投票。把两个勾选框都取消,看看没有随机性时会发生什么。
How Bootstrap Sampling Works
| Tree | Bootstrap Sample (row numbers) | Out-of-Bag Rows (never picked) |
|---|---|---|
| Tree 1 | 1, 3, 3, 5, 7, 7, 9, 2, 4, 4 | 6, 8, 10 |
| Tree 2 | 2, 4, 6, 6, 8, 1, 3, 9, 9, 5 | 7, 10 |
| Tree 3 | 10, 2, 5, 5, 1, 8, 3, 7, 6, 6 | 4, 9 |
| Tree 4 | 7, 9, 1, 4, 4, 6, 2, 10, 3, 8 | 5 |
Try It — Bootstrap Sampler
Draw the tickets one at a time, or a full sample at once. Orange tickets were never picked — they are the out-of-bag rows. Then repeat 1000 times to see the 63.2% rule appear.
Bootstrap Sampling कैसे काम करता है
| Tree | Bootstrap Sample (row नंबर) | Out-of-Bag Rows (कभी नहीं चुनी गईं) |
|---|---|---|
| Tree 1 | 1, 3, 3, 5, 7, 7, 9, 2, 4, 4 | 6, 8, 10 |
| Tree 2 | 2, 4, 6, 6, 8, 1, 3, 9, 9, 5 | 7, 10 |
| Tree 3 | 10, 2, 5, 5, 1, 8, 3, 7, 6, 6 | 4, 9 |
| Tree 4 | 7, 9, 1, 4, 4, 6, 2, 10, 3, 8 | 5 |
ख़ुद आज़माइए — Bootstrap Sampler
Tickets एक-एक करके निकालिए, या पूरा sample एक साथ। नारंगी tickets कभी नहीं चुने गए — वही out-of-bag rows हैं। फिर इसे 1000 बार दोहराइए और 63.2% का नियम उभरते देखिए।
Bootstrap Sampling 是怎么工作的
| Tree | Bootstrap Sample(行号) | Out-of-Bag 行(从没被抽到) |
|---|---|---|
| Tree 1 | 1, 3, 3, 5, 7, 7, 9, 2, 4, 4 | 6, 8, 10 |
| Tree 2 | 2, 4, 6, 6, 8, 1, 3, 9, 9, 5 | 7, 10 |
| Tree 3 | 10, 2, 5, 5, 1, 8, 3, 7, 6, 6 | 4, 9 |
| Tree 4 | 7, 9, 1, 4, 4, 6, 2, 10, 3, 8 | 5 |
动手试试 —— Bootstrap Sampler
一次抽一张票,或者一次抽完整个 sample。橙色的票从没被抽到 —— 它们就是 out-of-bag 行。然后重复 1000 次,看 63.2% 规则出现。
Every row is out-of-bag for about 37% of the trees. To score a row, use only the trees that never saw it and let them vote.
Do this for every row and compare with the true labels — that is the OOB score.
It is a nearly unbiased estimate of accuracy on new data, and you get it without a separate validation set. Set oob_score=True in scikit-learn.
Visual Diagram — Inside a Random Forest
'sqrt', int(√20) = 4 of the 20 — and picks the best split among them.Classification vs Regression
| Tree | Prediction |
|---|---|
| Tree 1 | Spam |
| Tree 2 | Spam |
| Tree 3 | Not Spam |
| Tree 4 | Spam |
| Tree 5 | Spam |
| Final | Spam (4 of 5 votes) |
| Tree | Predicted Price |
|---|---|
| Tree 1 | £312,000 |
| Tree 2 | £298,500 |
| Tree 3 | £325,000 |
| Tree 4 | £310,000 |
| Tree 5 | £304,500 |
| Final | £310,000 (mean) |
In the spam example, 4 of 5 trees say “Spam”, so the forest is about 80% sure. predict_proba() gives you this number.
You can use it to rank customers or to move the decision threshold (see Section 12).
Python Implementation
Classification — Predicting Customer Churn
हर row लगभग 37% trees के लिए out-of-bag होती है। किसी row को score करने के लिए सिर्फ़ उन trees को लीजिए जिन्होंने उसे कभी नहीं देखा, और उन्हें vote करने दीजिए।
हर row के लिए ऐसा कीजिए और असली labels से मिलाइए — यही OOB score है।
यह नए data पर accuracy का लगभग unbiased अंदाज़ा है, और यह आपको अलग validation set के बिना मिलता है। scikit-learn में oob_score=True set कीजिए।
Visual Diagram — Random Forest के अंदर
'sqrt' के साथ 20 में से int(√20) = 4 — और उनमें से सबसे अच्छा split चुनता है।Classification बनाम Regression
| Tree | Prediction |
|---|---|
| Tree 1 | Spam |
| Tree 2 | Spam |
| Tree 3 | Not Spam |
| Tree 4 | Spam |
| Tree 5 | Spam |
| आख़िरी | Spam (5 में से 4 votes) |
| Tree | Predicted Price |
|---|---|
| Tree 1 | £312,000 |
| Tree 2 | £298,500 |
| Tree 3 | £325,000 |
| Tree 4 | £310,000 |
| Tree 5 | £304,500 |
| आख़िरी | £310,000 (mean) |
Spam वाले example में 5 में से 4 trees “Spam” कहते हैं, इसलिए forest लगभग 80% पक्का है। predict_proba() आपको यही नंबर देता है।
आप इससे customers को rank कर सकते हैं या decision threshold खिसका सकते हैं (सेक्शन 12 देखिए)।
Python Implementation
Classification — Customer Churn का Prediction
每一行对大约 37% 的 tree 来说都是 out-of-bag。要给一行打分,只用从没见过它的 tree,让它们投票。
对每一行都这样做,再和真实的 label 比较 —— 这就是 OOB score。
它是对新数据上 accuracy 的一个几乎 unbiased 的估计,而且你不需要单独的 validation set 就能得到它。在 scikit-learn 中设置 oob_score=True。
图解 —— Random Forest 的内部
'sqrt' 时,是 20 个中的 int(√20) = 4 个 —— 然后在它们之中选出最好的 split。Classification vs Regression
| Tree | 预测 |
|---|---|
| Tree 1 | 垃圾邮件 |
| Tree 2 | 垃圾邮件 |
| Tree 3 | 正常邮件 |
| Tree 4 | 垃圾邮件 |
| Tree 5 | 垃圾邮件 |
| 最终 | 垃圾邮件(5 票中 4 票) |
| Tree | 预测价格 |
|---|---|
| Tree 1 | £312,000 |
| Tree 2 | £298,500 |
| Tree 3 | £325,000 |
| Tree 4 | £310,000 |
| Tree 5 | £304,500 |
| 最终 | £310,000(平均值) |
在垃圾邮件的例子中,5 棵 tree 中有 4 棵说“垃圾邮件”,所以 forest 大约有 80% 的把握。predict_proba() 会给你这个数字。
你可以用它给客户排序,或者移动 decision threshold(见第 12 节)。
Python 实现
Classification —— 预测客户流失
from sklearn.ensemble import RandomForestClassifier
from sklearn.model_selection import train_test_split
from sklearn.metrics import classification_report
from sklearn.datasets import make_classification
# Simulated churn data: 5,000 customers, 15 features
X, y = make_classification(n_samples=5000, n_features=15, n_informative=10,
n_redundant=3, random_state=42)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
rf = RandomForestClassifier(
n_estimators=300, # number of trees
max_features='sqrt', # features tried per split -> sqrt(15) ~ 3
max_depth=None, # grow trees fully
min_samples_leaf=1, # smallest allowed leaf
bootstrap=True, # bagging on
oob_score=True, # free out-of-bag estimate
n_jobs=-1, # use all CPU cores
random_state=42
)
rf.fit(X_train, y_train)
print(f"OOB score (free estimate): {rf.oob_score_:.4f}")
print(f"Test accuracy: {rf.score(X_test, y_test):.4f}\n")
print(classification_report(y_test, rf.predict(X_test), digits=3))
The OOB score (95.5%) and the test accuracy (94.8%) are very close. The OOB score was free — it used no test data.
Regression — Predicting House Prices
We use the California housing data (one row per district, 1990 census). Note that total_bedrooms has 207 missing values.
OOB score (95.5%) और test accuracy (94.8%) बहुत पास हैं। OOB score मुफ़्त मिला — इसमें कोई test data इस्तेमाल नहीं हुआ।
Regression — घरों की कीमत का Prediction
हम California housing data इस्तेमाल करते हैं (हर district की एक row, 1990 की जनगणना)। ध्यान दीजिए कि total_bedrooms में 207 missing values हैं।
OOB score(95.5%)和 test accuracy(94.8%)非常接近。OOB score 是免费得到的 —— 它没有用任何 test data。
Regression —— 预测房价
我们用 California housing 数据(每个地区一行,来自 1990 年的人口普查)。注意 total_bedrooms 有 207 个缺失值。
import pandas as pd
from sklearn.ensemble import RandomForestRegressor
from sklearn.model_selection import train_test_split
from sklearn.metrics import mean_absolute_error, r2_score
# California housing (1990 census), 20,640 districts
url = "https://raw.githubusercontent.com/ageron/handson-ml2/master/datasets/housing/housing.csv"
df = pd.read_csv(url)
X = df.drop(columns=["median_house_value", "ocean_proximity"])
y = df["median_house_value"]
print(f"Missing values in total_bedrooms: {X['total_bedrooms'].isna().sum()}")
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
rf_reg = RandomForestRegressor(
n_estimators=300,
max_features=1.0, # regression default: try all features
oob_score=True,
n_jobs=-1,
random_state=42
)
rf_reg.fit(X_train, y_train) # scikit-learn >= 1.4 accepts the NaN values
y_pred = rf_reg.predict(X_test)
print(f"OOB R²: {rf_reg.oob_score_:.4f}")
print(f"Test R²: {r2_score(y_test, y_pred):.4f}")
print(f"MAE: ${mean_absolute_error(y_test, y_pred):,.0f}")
Speed: set n_jobs=-1. The trees are independent, so they can be built on all CPU cores at the same time.
On an 8-core machine this is often 5–8× faster, with exactly the same results.
Missing values: since scikit-learn 1.4, Random Forest accepts NaN directly — that is why the code above works without imputation. In older versions you must fill the gaps first.
Key Hyperparameters
| Parameter | Default | What It Controls | Tuning Advice |
|---|---|---|---|
n_estimators | 100 | Number of trees | More is better until the error goes flat. 300–500 is a good start. |
max_features | 'sqrt' (classifier) 1.0 (regressor) | Features tried at each split | Usually the most important one to tune. |
max_depth | None | Maximum depth of each tree | None = grow fully. Limit it to save memory or to smooth noisy data. |
min_samples_leaf | 1 | Smallest number of rows in a leaf | Try 2–10 on noisy data. Also gives smoother probabilities. |
min_samples_split | 2 | Rows needed to split a node | Rarely needed if you tune min_samples_leaf. |
bootstrap | True | Use bagging or not | Keep True. False removes one source of diversity and the OOB score. |
max_samples | None | Size of each bootstrap sample | e.g. 0.5 = each tree sees half the rows. Faster on big data. |
oob_score | False | Compute the OOB score | Set True — a free accuracy check. |
class_weight | None | Weights for rare classes | 'balanced' or 'balanced_subsample' for imbalanced data. |
Try It — More Trees & the OOB Score
The forest grows from 1 to 300 trees. Watch the test error and the OOB error fall and then go flat. They never turn upward.
Speed: n_jobs=-1 set कीजिए। Trees एक-दूसरे पर निर्भर नहीं हैं, इसलिए वे सारे CPU cores पर एक साथ बन सकते हैं।
8-core machine पर यह अक्सर 5–8× तेज़ होता है, और नतीजे बिल्कुल वही रहते हैं।
Missing values: scikit-learn 1.4 से Random Forest सीधे NaN स्वीकार करता है — इसीलिए ऊपर का code बिना imputation के चलता है। पुराने versions में आपको पहले खाली जगहें भरनी होंगी।
मुख्य Hyperparameters
| Parameter | Default | यह क्या control करता है | Tuning सलाह |
|---|---|---|---|
n_estimators | 100 | Trees की संख्या | जब तक error सपाट न हो जाए, ज़्यादा बेहतर है। 300–500 अच्छी शुरुआत है। |
max_features | 'sqrt' (classifier) 1.0 (regressor) | हर split पर आज़माए जाने वाले features | आमतौर पर tune करने के लिए सबसे ज़रूरी। |
max_depth | None | हर tree की अधिकतम गहराई | None = पूरा बढ़ने दो। Memory बचाने या noisy data को smooth करने के लिए इसे सीमित कीजिए। |
min_samples_leaf | 1 | एक leaf में rows की सबसे छोटी संख्या | Noisy data पर 2–10 आज़माइए। इससे probabilities भी smooth होती हैं। |
min_samples_split | 2 | एक node को split करने के लिए ज़रूरी rows | अगर आप min_samples_leaf tune करते हैं, तो इसकी ज़रूरत कम ही पड़ती है। |
bootstrap | True | Bagging इस्तेमाल करें या नहीं | True रखिए। False diversity का एक स्रोत और OOB score दोनों हटा देता है। |
max_samples | None | हर bootstrap sample का size | जैसे 0.5 = हर tree आधी rows देखता है। बड़े data पर तेज़। |
oob_score | False | OOB score निकालें | True set कीजिए — accuracy की मुफ़्त जाँच। |
class_weight | None | Rare classes के लिए weights | Imbalanced data के लिए 'balanced' या 'balanced_subsample'। |
ख़ुद आज़माइए — More Trees & the OOB Score
Forest 1 से 300 trees तक बढ़ता है। देखिए कि test error और OOB error गिरते हैं और फिर सपाट हो जाते हैं। वे कभी ऊपर नहीं मुड़ते।
速度:设置 n_jobs=-1。各棵 tree 彼此独立,所以可以同时在所有 CPU 核心上建。
在 8 核的机器上,这通常快 5–8 倍,而且结果完全一样。
缺失值:从 scikit-learn 1.4 开始,Random Forest 可以直接接受 NaN —— 所以上面的代码不用 imputation 也能运行。在旧版本里,你必须先把空缺填上。
关键的 Hyperparameter
| 参数 | 默认值 | 控制什么 | 调参建议 |
|---|---|---|---|
n_estimators | 100 | tree 的数量 | 越多越好,直到 error 变平。300–500 是个好起点。 |
max_features | 'sqrt'(classifier) 1.0(regressor) | 每次 split 时尝试的 feature 数 | 通常是最需要调的一个。 |
max_depth | None | 每棵 tree 的最大深度 | None = 完全长开。限制它可以省内存,或者让有噪声的数据更平滑。 |
min_samples_leaf | 1 | 一个 leaf 里最少的行数 | 在有噪声的数据上试试 2–10。还能让概率更平滑。 |
min_samples_split | 2 | split 一个 node 需要的行数 | 如果你调了 min_samples_leaf,就很少需要它。 |
bootstrap | True | 是否使用 bagging | 保持 True。False 会去掉一个多样性的来源,也会失去 OOB score。 |
max_samples | None | 每个 bootstrap sample 的大小 | 例如 0.5 = 每棵 tree 看一半的行。在大数据上更快。 |
oob_score | False | 是否计算 OOB score | 设成 True —— 免费的 accuracy 检查。 |
class_weight | None | 少见 class 的权重 | 不平衡的数据用 'balanced' 或 'balanced_subsample'。 |
动手试试 —— More Trees & the OOB Score
forest 从 1 棵 tree 长到 300 棵。看 test error 和 OOB error 先下降,然后变平。它们永远不会往上走。
Hyperparameter Tuning with RandomizedSearchCV
Random search tries a fixed number of random combinations. It is much faster than trying every combination (grid search) and usually finds an equally good answer.
RandomizedSearchCV से Hyperparameter Tuning
Random search एक तय संख्या में random combinations आज़माता है। यह हर combination आज़माने (grid search) से कहीं तेज़ है और आमतौर पर उतना ही अच्छा जवाब ढूँढ लेता है।
用 RandomizedSearchCV 做 Hyperparameter 调参
随机搜索尝试固定数量的随机组合。它比尝试每一种组合(grid search)快得多,而且通常能找到一样好的答案。
# Tune the churn classifier: X_train, y_train come from the classification example
from scipy.stats import randint
from sklearn.model_selection import RandomizedSearchCV
param_dist = {
"n_estimators": randint(100, 400),
"max_features": ["sqrt", "log2", 0.3, 0.5],
"max_depth": [None, 10, 20],
"min_samples_leaf": randint(1, 6),
}
search = RandomizedSearchCV(
RandomForestClassifier(n_jobs=-1, random_state=42),
param_distributions=param_dist,
n_iter=20, # try 20 random combinations
cv=5,
scoring="f1",
n_jobs=-1,
random_state=42,
)
search.fit(X_train, y_train)
print("Best params:", search.best_params_)
print(f"Best CV F1: {search.best_score_:.4f}")
print(f"Test F1: {search.score(X_test, y_test):.4f}")
The tuned model reaches a test F1 of 0.952 — a small gain over the defaults. This is typical: Random Forest works well out of the box, and tuning usually adds only a little.
Feature Importance
A big practical advantage of Random Forest is that it can rank the features.
The built-in method is Mean Decrease in Impurity (MDI): every time a feature is used for a split, we add up how much it reduced the Gini impurity (or the MSE for regression). Then we average over all trees.
This is what feature_importances_ gives you.
Tuned model test F1 0.952 तक पहुँचता है — defaults से थोड़ा-सा बेहतर। ऐसा आमतौर पर होता है: Random Forest शुरू से ही अच्छा काम करता है, और tuning से आमतौर पर बस थोड़ा फ़ायदा होता है।
Feature Importance
Random Forest का एक बड़ा practical फ़ायदा यह है कि यह features को rank कर सकता है।
Built-in तरीक़ा है Mean Decrease in Impurity (MDI): जब भी कोई feature split के लिए इस्तेमाल होता है, हम जोड़ते हैं कि उसने Gini impurity (या regression में MSE) कितनी घटाई। फिर सारे trees का average लेते हैं।
feature_importances_ आपको यही देता है।
调参后的 model 在 test 上的 F1 达到 0.952 —— 比默认值略有提升。这很常见:Random Forest 开箱即用就很好,调参通常只多带来一点点提升。
Feature Importance
Random Forest 的一大实用优点是它能给 feature 排名。
内置的方法是 Mean Decrease in Impurity(MDI):每当一个 feature 被用来 split,我们就把它让 Gini impurity 减少了多少加起来(regression 则用 MSE)。然后在所有 tree 上取平均。
这就是 feature_importances_ 给你的东西。
import numpy as np
import pandas as pd
feature_names = X.columns
# ── MDI importance (built in, computed on the training data) ──
mdi = pd.DataFrame({
"feature": feature_names,
"importance": rf_reg.feature_importances_,
"std": np.std([t.feature_importances_ for t in rf_reg.estimators_], axis=0),
}).sort_values("importance", ascending=False)
print(mdi.round(4).to_string(index=False))
1. It is computed on the training data, so it can reward features that only helped the trees memorise noise.
2. It is biased toward high-cardinality features — numbers with many unique values, like an ID column — because they offer many possible split points.
Permutation importance is less biased: shuffle one column in the test data and measure how much the score drops. It costs more compute.
Permutation Importance
1. यह training data पर निकाला जाता है, इसलिए यह उन features को भी इनाम दे सकता है जिन्होंने trees को सिर्फ़ noise रटने में मदद की।
2. यह high-cardinality features की तरफ़ झुका होता है — ऐसे नंबर जिनकी बहुत सारी unique values हों, जैसे ID column — क्योंकि उनमें split के बहुत सारे मौक़े होते हैं।
Permutation importance कम biased है: test data में एक column को shuffle कीजिए और देखिए कि score कितना गिरता है। इसमें compute ज़्यादा लगता है।
Permutation Importance
1. 它是在 training data 上算的,所以可能会奖励那些只帮 tree 死记噪声的 feature。
2. 它偏向 high-cardinality 的 feature —— 也就是有很多不同值的数字,比如 ID 列 —— 因为它们提供了很多可能的 split 点。
Permutation importance 的 bias 更小:在 test data 里打乱一列,看 score 下降了多少。它需要更多计算。
Permutation Importance
from sklearn.inspection import permutation_importance
result = permutation_importance(rf_reg, X_test, y_test,
n_repeats=10, n_jobs=-1, random_state=42)
perm = pd.DataFrame({
"feature": feature_names,
"importance": result.importances_mean, # drop in R² when the column is shuffled
"std": result.importances_std,
}).sort_values("importance", ascending=False)
print(perm.round(4).to_string(index=False))
The two methods disagree! MDI says median_income is by far the most important. Permutation importance puts latitude and longitude first.
Why? Latitude and longitude work as a team — together they say where the house is. Shuffle one of them, and the location becomes nonsense, so R² falls a lot.
MDI splits the credit between many small splits. Neither number is “the truth”; they answer different questions. When features are correlated, read both with care.
Try It — MDI vs Permutation Importance
The target depends only on income and credit. Add a useless customer_id column (a unique random number per row) and see which method is fooled.
दोनों तरीक़े सहमत नहीं हैं! MDI कहता है कि median_income सबसे ज़्यादा ज़रूरी है, और बहुत आगे है। Permutation importance latitude और longitude को पहले रखता है।
क्यों? Latitude और longitude एक team की तरह काम करते हैं — दोनों मिलकर बताते हैं कि घर कहाँ है। इनमें से एक को shuffle कीजिए, तो location बेमतलब हो जाती है, इसलिए R² बहुत गिरता है।
MDI credit को कई छोटे splits में बाँट देता है। कोई भी नंबर “सच्चाई” नहीं है; दोनों अलग-अलग सवालों के जवाब देते हैं। जब features correlated हों, तो दोनों को ध्यान से पढ़िए।
ख़ुद आज़माइए — MDI vs Permutation Importance
Target सिर्फ़ income और credit पर निर्भर है। एक बेकार customer_id column जोड़िए (हर row के लिए एक unique random नंबर) और देखिए कि कौन-सा तरीक़ा धोखा खाता है।
两种方法的结论不一样!MDI 说 median_income 远远是最重要的。Permutation importance 把 latitude 和 longitude 排在最前面。
为什么?latitude 和 longitude 是一个团队 —— 它们合在一起才说明房子在哪里。打乱其中一个,位置就变得毫无意义,所以 R² 会下降很多。
MDI 把功劳分给了很多个小的 split。没有哪个数字是“真相”;它们回答的是不同的问题。当 feature 之间有 correlation 时,两个都要仔细看。
动手试试 —— MDI vs Permutation Importance
target 只取决于 income 和 credit。加入一个没用的 customer_id 列(每行一个唯一的随机数),看看哪种方法会被骗。
Bias–Variance: Single Tree vs Forest
Suppose we have N trees. Each has variance σ², and any two trees have correlation ρ.
The variance of their average is:
Var(forest) = ρ·σ² + (1−ρ)/N · σ²
As N grows, the second term goes to zero. The first term ρ·σ² stays — no number of trees can remove it.
So making the trees less correlated (smaller ρ) matters as much as adding trees. That is exactly what max_features does.
Averaging does not change the bias: the forest’s bias is about the same as one tree’s.
Try It — max_features & Tree Correlation
Move max_features from 1 to 8. Watch three things: how good one tree is, how alike the trees are (ρ), and how good the forest is. Press Compute all 8 to draw the full curves.
Bias–Variance: एक Tree बनाम Forest
मान लीजिए हमारे पास N trees हैं। हर एक का variance σ² है, और किन्हीं दो trees के बीच correlation ρ है।
उनके average का variance है:
Var(forest) = ρ·σ² + (1−ρ)/N · σ²
जैसे-जैसे N बढ़ता है, दूसरा term zero की तरफ़ जाता है। पहला term ρ·σ² बना रहता है — कितने भी trees उसे नहीं हटा सकते।
इसलिए trees को कम correlated बनाना (छोटा ρ) उतना ही ज़रूरी है जितना trees जोड़ना। max_features ठीक यही करता है।
Averaging bias को नहीं बदलता: forest का bias लगभग एक tree जितना ही होता है।
ख़ुद आज़माइए — max_features & Tree Correlation
max_features को 1 से 8 तक खिसकाइए। तीन चीज़ें देखिए: एक tree कितना अच्छा है, trees कितने एक जैसे हैं (ρ), और forest कितना अच्छा है। पूरे curves बनाने के लिए सारे 8 निकालें दबाइए।
Bias–Variance:一棵 Tree vs 一片 Forest
假设我们有 N 棵 tree。每棵的 variance 是 σ²,任意两棵 tree 之间的 correlation 是 ρ。
它们平均值的 variance 是:
Var(forest) = ρ·σ² + (1−ρ)/N · σ²
当 N 变大时,第二项趋近于 0。第一项 ρ·σ² 会留下来 —— 再多的 tree 也去不掉它。
所以让各棵 tree 的 correlation 更低(ρ 更小)和增加 tree 一样重要。这正是 max_features 做的事。
取平均不会改变 bias:forest 的 bias 和一棵 tree 的 bias 差不多。
动手试试 —— max_features & Tree Correlation
把 max_features 从 1 移到 8。看三件事:一棵 tree 有多好,各棵 tree 有多相似(ρ),以及 forest 有多好。按 计算全部 8 个 画出完整的曲线。
| Model | Bias | Variance | Overfit Risk | Typical Use |
|---|---|---|---|---|
| Single shallow tree | High | Low | Low | Simple, readable rules |
| Single deep tree | Low | Very High | Severe | Rarely useful alone |
| Random Forest | Low (same as a deep tree) | Low | Low | General-purpose workhorse ✅ |
| Gradient Boosting | Very Low | Medium | Moderate | Top accuracy, needs tuning |
When to Use Random Forest
Handling Class Imbalance
Random Forest can struggle when one class is rare (fraud detection: 97% normal, 3% fraud). Most bootstrap samples contain very few fraud rows, so most trees learn to say “normal”. Here are the options:
class_weight='balanced' — rare classes get bigger weights (inverse to their frequency). Easy; no change to the data.
class_weight='balanced_subsample' — the same, but the weights are recomputed for each tree’s bootstrap sample.
imbalanced-learn package (pip install imbalanced-learn) — each tree trains on a balanced sample with the majority class undersampled.
predict_proba() and predict “fraud” when the score is above 0.3 instead of 0.5. This raises recall on the rare class.
| Model | Bias | Variance | Overfit का ख़तरा | आम इस्तेमाल |
|---|---|---|---|---|
| एक shallow tree | High | Low | Low | आसान, पढ़ने लायक नियम |
| एक deep tree | Low | Very High | गंभीर | अकेले शायद ही काम का |
| Random Forest | Low (deep tree जितना) | Low | Low | हर काम का भरोसेमंद model ✅ |
| Gradient Boosting | Very Low | Medium | मध्यम | सबसे ऊँची accuracy, tuning चाहिए |
Random Forest कब इस्तेमाल करें
Class Imbalance को संभालना
जब कोई class rare हो, तो Random Forest को मुश्किल हो सकती है (fraud detection: 97% normal, 3% fraud)। ज़्यादातर bootstrap samples में बहुत कम fraud rows होती हैं, इसलिए ज़्यादातर trees “normal” कहना सीख जाते हैं। ये रहे विकल्प:
class_weight='balanced' — rare classes को बड़े weights मिलते हैं (उनकी frequency के उल्टे अनुपात में)। आसान; data में कोई बदलाव नहीं।
class_weight='balanced_subsample' — वही, पर weights हर tree के bootstrap sample के लिए फिर से निकाले जाते हैं।
imbalanced-learn package (pip install imbalanced-learn) से आता है — हर tree एक balanced sample पर train होता है, जिसमें majority class को undersample किया जाता है।
predict_proba() इस्तेमाल कीजिए और जब score 0.5 के बजाय 0.3 से ऊपर हो, तब “fraud” predict कीजिए। इससे rare class पर recall बढ़ता है।
| Model | Bias | Variance | Overfit 风险 | 典型用途 |
|---|---|---|---|---|
| 一棵浅的 tree | 高 | 低 | 低 | 简单、好读的规则 |
| 一棵深的 tree | 低 | 非常高 | 严重 | 单独用时很少有用 |
| Random Forest | 低(和一棵深的 tree 一样) | 低 | 低 | 通用的主力 ✅ |
| Gradient Boosting | 非常低 | 中等 | 中等 | accuracy 最高,需要调参 |
什么时候用 Random Forest
处理 Class Imbalance
当一个 class 很少见时(欺诈检测:97% 正常,3% 欺诈),Random Forest 可能会遇到困难。 大多数 bootstrap sample 里只有很少的欺诈行,所以大多数 tree 学会了说“正常”。下面是几种做法:
class_weight='balanced' —— 少见的 class 得到更大的权重(和它们的频率成反比)。很简单;不用改动数据。
class_weight='balanced_subsample' —— 和上面一样,但权重会针对每棵 tree 的 bootstrap sample 重新计算。
imbalanced-learn 包(pip install imbalanced-learn)—— 每棵 tree 都在一个平衡的 sample 上训练,majority class 会被 undersample。
predict_proba(),当 score 高于 0.3(而不是 0.5)时就预测为“欺诈”。这会提高少见 class 的 recall。
from sklearn.datasets import make_classification
from sklearn.ensemble import RandomForestClassifier
from sklearn.model_selection import train_test_split
from sklearn.metrics import precision_score, recall_score
from imblearn.ensemble import BalancedRandomForestClassifier
# Fraud-like data: about 3% positives
X, y = make_classification(n_samples=20000, n_features=20, n_informative=6,
weights=[0.97, 0.03], class_sep=0.8, random_state=7)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.25,
stratify=y, random_state=7)
def report(name, y_pred):
print(f"{name:28s} recall={recall_score(y_test, y_pred):.3f} "
f"precision={precision_score(y_test, y_pred):.3f}")
rf = RandomForestClassifier(n_estimators=300, n_jobs=-1, random_state=42).fit(X_train, y_train)
report("Plain RF", rf.predict(X_test))
rf_bal = RandomForestClassifier(n_estimators=300, class_weight="balanced_subsample",
min_samples_leaf=5, n_jobs=-1, random_state=42).fit(X_train, y_train)
report("class_weight + leaf=5", rf_bal.predict(X_test))
brf = BalancedRandomForestClassifier(n_estimators=300, sampling_strategy="all",
replacement=True, bootstrap=False,
n_jobs=-1, random_state=42).fit(X_train, y_train)
report("BalancedRandomForest", brf.predict(X_test))
proba = rf.predict_proba(X_test)[:, 1]
report("Plain RF, threshold 0.3", (proba >= 0.3).astype(int))
Plain RF catches only 16% of fraud. Class weights help a little (28%). The balanced forest catches 68%, but now most of its alarms are false (precision 0.31). Simply lowering the threshold to 0.3 gives a good middle ground. There is no free lunch: you always trade precision for recall. Choose the threshold from the real cost of each mistake.
Try It — Imbalanced Classes
Fraud is only about 4% of the rows. Slide the threshold and watch caught fraud and false alarms change. Then switch to a balanced bootstrap.
सादा RF सिर्फ़ 16% fraud पकड़ता है। Class weights थोड़ी मदद करते हैं (28%)। Balanced forest 68% पकड़ता है, पर अब उसके ज़्यादातर alarms झूठे हैं (precision 0.31)। बस threshold को 0.3 तक घटाने से अच्छा बीच का रास्ता मिलता है। मुफ़्त में कुछ नहीं मिलता: आप हमेशा recall के लिए precision का सौदा करते हैं। हर ग़लती की असली कीमत देखकर threshold चुनिए।
ख़ुद आज़माइए — Imbalanced Classes
Fraud सिर्फ़ लगभग 4% rows है। Threshold खिसकाइए और देखिए कि पकड़ा गया fraud और झूठे alarms कैसे बदलते हैं। फिर balanced bootstrap पर switch कीजिए।
普通的 RF 只抓到 16% 的欺诈。Class weight 有一点帮助(28%)。balanced forest 抓到 68%,但现在它的大多数警报都是误报(precision 0.31)。 只要把 threshold 降到 0.3,就能得到一个不错的折中。天下没有免费的午餐:你总是在用 precision 换 recall。请根据每种错误的真实代价来选 threshold。
动手试试 —— Imbalanced Classes
欺诈只占大约 4% 的行。滑动 threshold,看抓到的欺诈和误报怎么变化。然后切换到 balanced bootstrap。
A Complete Real-World Example — Titanic Survival
एक पूरा Real-World Example — Titanic Survival
一个完整的真实例子 —— Titanic 生存预测
import pandas as pd
from sklearn.ensemble import RandomForestClassifier
from sklearn.model_selection import cross_val_score
url = "https://raw.githubusercontent.com/datasciencedojo/datasets/master/titanic.csv"
df = pd.read_csv(url) # 891 passengers
# Simple preprocessing (no scaling needed for trees)
df["Age"] = df["Age"].fillna(df["Age"].median())
df["Embarked"] = df["Embarked"].fillna("S")
df["Sex"] = df["Sex"].map({"male": 0, "female": 1})
df["Embarked"] = df["Embarked"].map({"S": 0, "C": 1, "Q": 2})
features = ["Pclass", "Sex", "Age", "SibSp", "Parch", "Fare", "Embarked"]
X, y = df[features], df["Survived"]
rf = RandomForestClassifier(n_estimators=500, max_features="sqrt", min_samples_leaf=2,
oob_score=True, n_jobs=-1, random_state=42)
cv_scores = cross_val_score(rf, X, y, cv=5, scoring="accuracy")
print(f"CV accuracy: {cv_scores.mean():.4f} +/- {cv_scores.std():.4f}")
rf.fit(X, y)
print(f"OOB score: {rf.oob_score_:.4f}\n")
for feat, imp in sorted(zip(features, rf.feature_importances_), key=lambda x: -x[1]):
print(f" {feat:9s}: {imp:.4f}")
Cross-validation (83.2%) and the OOB score (83.2%) agree almost perfectly. Sex is the strongest feature (“women and children first”). Remember the MDI warning: Fare and Age have many unique values, so MDI may rank them a bit too high.
We did not scale Age, Fare or any other feature. Trees split on thresholds (“Age < 9.5?”), not on distances, so the scale of a feature does not matter — only the order of its values. This makes Random Forest easier to use than SVMs, KNN or neural networks, which all need careful scaling.
Random Forest vs Gradient Boosting — Quick Comparison
| Property | Random Forest | Gradient Boosting (XGBoost / LightGBM) |
|---|---|---|
| How trees are built | In parallel — independent | One after another — each fixes the previous errors |
| Tree type | Deep trees (low bias); averaging cuts variance | Shallow trees (high bias); boosting cuts bias |
| Overfitting risk | Low — bagging protects well | Higher — needs learning rate and early stopping |
| Training speed | Fast (parallel) | Sequential, but modern libraries are very fast |
| Hyperparameter sensitivity | Low — defaults work well | High — needs tuning to shine |
| Peak accuracy | Very good | Often the best on tabular data |
| Missing values | Supported in scikit-learn ≥ 1.4 | Handled natively by XGBoost, LightGBM, HistGradientBoosting |
| Best choice when… | You need a fast, robust baseline | You need the last bit of accuracy |
Start with Random Forest as your baseline — it is fast, robust and good with almost no tuning. If you need the last 1–3% of accuracy, try LightGBM or XGBoost and tune carefully. Many production systems keep Random Forest because the small gain from boosting is not worth the extra work.
Golden Rules
n_jobs=-1. The trees are independent, so using all cores is free speed. The default uses only one core.
oob_score=True. You get a nearly unbiased estimate of accuracy on new data at almost no extra cost. Check it before you touch the test set.
max_features first — it controls how different the trees are. Then min_samples_leaf (2–5 for noisy data).
For n_estimators, just use enough trees that the OOB error is flat (often 300–500).
class_weight='balanced_subsample', a balanced forest, and — often most useful — a tuned decision threshold.
max_features and min_samples_leaf.)
permutation_importance from sklearn.inspection).
It is less biased — but correlated features can still share or hide importance, so read both with care.
Cross-validation (83.2%) और OOB score (83.2%) लगभग पूरी तरह सहमत हैं। Sex सबसे मज़बूत feature है (“पहले औरतें और बच्चे”)। MDI वाली चेतावनी याद रखिए: Fare और Age में बहुत सारी unique values हैं, इसलिए MDI उन्हें थोड़ा ज़्यादा ऊँचा rank कर सकता है।
हमने Age, Fare या किसी और feature को scale नहीं किया। Trees thresholds पर split करते हैं (“Age < 9.5?”), distances पर नहीं, इसलिए feature का scale मायने नहीं रखता — सिर्फ़ उसकी values का क्रम मायने रखता है। इससे Random Forest को SVMs, KNN या neural networks से इस्तेमाल करना आसान है, क्योंकि उन सबको सावधानी से scaling चाहिए।
Random Forest बनाम Gradient Boosting — जल्दी से तुलना
| गुण | Random Forest | Gradient Boosting (XGBoost / LightGBM) |
|---|---|---|
| Trees कैसे बनते हैं | Parallel में — एक-दूसरे से स्वतंत्र | एक के बाद एक — हर tree पिछली errors ठीक करता है |
| Tree का प्रकार | Deep trees (low bias); averaging variance घटाता है | Shallow trees (high bias); boosting bias घटाता है |
| Overfitting का ख़तरा | कम — bagging अच्छी सुरक्षा देता है | ज़्यादा — learning rate और early stopping चाहिए |
| Training speed | तेज़ (parallel) | Sequential, पर आधुनिक libraries बहुत तेज़ हैं |
| Hyperparameter sensitivity | कम — defaults अच्छा काम करते हैं | ज़्यादा — चमकने के लिए tuning चाहिए |
| सबसे ऊँची accuracy | बहुत अच्छी | Tabular data पर अक्सर सबसे अच्छी |
| Missing values | scikit-learn ≥ 1.4 में supported | XGBoost, LightGBM, HistGradientBoosting ख़ुद संभालते हैं |
| सबसे अच्छा चुनाव जब… | आपको तेज़, robust baseline चाहिए | आपको accuracy का आख़िरी टुकड़ा चाहिए |
Random Forest को अपना baseline बनाकर शुरू कीजिए — यह तेज़, robust और लगभग बिना tuning के अच्छा है। अगर आपको accuracy का आख़िरी 1–3% चाहिए, तो LightGBM या XGBoost आज़माइए और ध्यान से tune कीजिए। बहुत सारे production systems Random Forest ही रखते हैं, क्योंकि boosting से मिलने वाला छोटा फ़ायदा अतिरिक्त मेहनत के लायक नहीं होता।
सुनहरे नियम
n_jobs=-1 set कीजिए। Trees एक-दूसरे से स्वतंत्र हैं, इसलिए सारे cores इस्तेमाल करना मुफ़्त की speed है। Default सिर्फ़ एक core इस्तेमाल करता है।
oob_score=True set कीजिए। आपको लगभग बिना किसी अतिरिक्त खर्च के नए data पर accuracy का लगभग unbiased अंदाज़ा मिलता है। Test set को छूने से पहले इसे देखिए।
max_features tune कीजिए — यह control करता है कि trees कितने अलग हैं। फिर min_samples_leaf (noisy data के लिए 2–5)।
n_estimators के लिए बस इतने trees लीजिए कि OOB error सपाट हो जाए (अक्सर 300–500)।
class_weight='balanced_subsample', एक balanced forest, और — अक्सर सबसे काम का — एक tuned decision threshold आज़माइए।
max_features और min_samples_leaf से control कीजिए।)
sklearn.inspection का permutation_importance)।
यह कम biased है — पर correlated features फिर भी importance को बाँट या छिपा सकते हैं, इसलिए दोनों को ध्यान से पढ़िए।
Cross-validation(83.2%)和 OOB score(83.2%)几乎完全一致。Sex 是最强的 feature(“妇女和儿童优先”)。记住 MDI 的警告:Fare 和 Age 有很多不同的值,所以 MDI 可能会把它们排得稍高一点。
我们没有对 Age、Fare 或任何其他 feature 做 scaling。 tree 按 threshold 来 split(“Age < 9.5?”),而不是按距离,所以 feature 的尺度不重要 —— 只有值的顺序重要。 这让 Random Forest 比 SVM、KNN 或 neural network 更好用,那些都需要仔细做 scaling。
Random Forest vs Gradient Boosting —— 快速比较
| 特点 | Random Forest | Gradient Boosting(XGBoost / LightGBM) |
|---|---|---|
| tree 是怎么建的 | 并行 —— 彼此独立 | 一棵接一棵 —— 每棵都修正前面的错误 |
| Tree 的类型 | 深的 tree(low bias);取平均降低 variance | 浅的 tree(high bias);boosting 降低 bias |
| Overfitting 风险 | 低 —— bagging 保护得很好 | 较高 —— 需要 learning rate 和 early stopping |
| 训练速度 | 快(并行) | 按顺序进行,但现代的库非常快 |
| 对 Hyperparameter 的敏感度 | 低 —— 默认值就很好用 | 高 —— 需要调参才能表现出色 |
| 最高 accuracy | 非常好 | 在表格数据上常常是最好的 |
| 缺失值 | scikit-learn ≥ 1.4 支持 | XGBoost、LightGBM、HistGradientBoosting 原生支持 |
| 最适合的情况… | 你需要一个快速、稳健的 baseline | 你需要榨出最后一点 accuracy |
先用 Random Forest 做 baseline —— 它快、稳健,几乎不用调参就很好。 如果你需要最后 1–3% 的 accuracy,就试试 LightGBM 或 XGBoost,并仔细调参。 很多生产系统一直在用 Random Forest,因为 boosting 带来的一点点提升不值得额外的工作。
黄金法则
n_jobs=-1。各棵 tree 彼此独立,所以用上所有核心就是白捡的速度。默认只用一个核心。
oob_score=True。你几乎不用额外代价,就能得到对新数据上 accuracy 的一个几乎 unbiased 的估计。在碰 test set 之前先看看它。
max_features —— 它控制各棵 tree 有多不同。然后调 min_samples_leaf(有噪声的数据用 2–5)。
对于 n_estimators,只要用足够多的 tree,让 OOB error 变平就行(通常是 300–500)。
class_weight='balanced_subsample'、balanced forest,以及 —— 常常最有用的 —— 调好的 decision threshold。
max_features 和 min_samples_leaf 来控制。)
sklearn.inspection 里的 permutation_importance)。
它的 bias 更小 —— 但有 correlation 的 feature 仍然可能分享或隐藏 importance,所以两个都要仔细看。