Level 5 — MasteryTree-Based & Instance Methods

Tree-Based & Instance Methods

90 minutes60 marksprintable — key stays hidden on paper

Chapter: 2.3 Tree-Based & Instance Methods Time limit: 90 minutes Total marks: 60 Instructions: Answer all three questions. Show full derivations. Code may be pseudocode or Python; correctness of logic matters more than syntax. Use ...... notation for math.


Question 1 — Splitting criteria, entropy vs Gini, and a proof (20 marks)

A binary-classification node contains NN samples with class-1 proportion pp.

(a) Write the Gini impurity G(p)G(p) and the Shannon entropy H(p)H(p) (base 2) for a binary node. Prove that G(p)12H(p)G(p) \le \tfrac{1}{2}H(p) for all p[0,1]p \in [0,1], using the inequality log2x1ln2(1x)-\log_2 x \ge \frac{1}{\ln 2}(1-x). (6)

(b) A dataset of 14 samples has 9 positives and 5 negatives. A candidate feature Wind splits into Weak (8 samples: 6 pos, 2 neg) and Strong (6 samples: 3 pos, 3 neg). Compute the parent entropy, the weighted child entropy, and the information gain to 3 decimals. (6)

(c) Compute the Gini-based weighted impurity of the same split and the Gini gain. State, with numerical justification, whether entropy and Gini agree on this split being an improvement. (4)

(d) Prove that for any node, information gain is non-negative (i.e. entropy is a concave function of pp, so splitting cannot increase expected impurity). State the geometric argument precisely. (4)


Question 2 — Ensembles: OOB, AdaBoost weight update, and bias–variance (22 marks)

(a) In bootstrap aggregating with nn training samples, derive the probability that a specific sample is not selected in a bootstrap sample of size nn, and its limiting value as nn\to\infty. State the expected fraction of out-of-bag (OOB) samples. (5)

(b) AdaBoost (discrete, binary labels yi{1,+1}y_i \in \{-1,+1\}): a weak learner hth_t has weighted error εt=0.25\varepsilon_t = 0.25. Derive the classifier weight αt=12ln1εtεt\alpha_t = \tfrac12 \ln\frac{1-\varepsilon_t}{\varepsilon_t} and compute it. Then give the weight-update rule and compute the multiplicative factor applied to a correctly classified point and to a misclassified point (before normalization). (6)

(c) Show that after the update in (b), if ZtZ_t is the normalization constant, then Zt=2εt(1εt)Z_t = 2\sqrt{\varepsilon_t(1-\varepsilon_t)}, and evaluate it for εt=0.25\varepsilon_t = 0.25. Explain why minimizing ZtZ_t at each round motivates the choice of αt\alpha_t. (6)

(d) Contrast bagging and boosting in terms of which component of test error (bias vs variance) each primarily reduces, and explain why boosting is more prone to overfitting noisy labels. (5)


Question 3 — KNN, distance geometry, curse of dimensionality (18 marks)

(a) Given points a=(1,2,2)a=(1,2,2), b=(4,6,2)b=(4,6,2), compute the Euclidean, Manhattan, and cosine distance (1cosθ1-\cos\theta) between them. Show all steps. (6)

(b) Write pseudocode for a weighted KNN classifier that weights neighbours by 1/d1/d and predicts by weighted majority vote. State the time complexity of one prediction over NN training points in DD dimensions. (5)

(c) Curse of dimensionality: for points uniformly distributed in the unit cube [0,1]D[0,1]^D, to capture a fraction rr of the data volume in a hypercubic neighbourhood the edge length must be =r1/D\ell = r^{1/D}. Compute \ell for r=0.01r=0.01 at D=1,10,100D=1, 10, 100. Interpret the implication for choosing KK and for local methods like KNN in high dimensions. (7)

Answer keyMark scheme & solutions

Question 1

(a) G(p)=2p(1p)G(p) = 2p(1-p); H(p)=plog2p(1p)log2(1p)H(p) = -p\log_2 p - (1-p)\log_2(1-p). (1) Using log2x1ln2(1x)-\log_2 x \ge \frac{1}{\ln 2}(1-x): H(p)=p(log2p)+(1p)(log2(1p))1ln2[p(1p)+(1p)p]=2p(1p)ln2H(p) = p(-\log_2 p) + (1-p)(-\log_2(1-p)) \ge \frac{1}{\ln 2}\big[p(1-p) + (1-p)p\big] = \frac{2p(1-p)}{\ln 2}. (3) So H(p)G(p)ln2H(p) \ge \frac{G(p)}{\ln 2}, i.e. G(p)(ln2)H(p)0.693H(p)G(p) \le (\ln 2)\,H(p) \approx 0.693\,H(p). Since ln2<1\ln 2 < 1, and in fact one shows G(p)12H(p)G(p)\le \tfrac12 H(p) holds pointwise (max ratio G/Hln2/20.3466G/H \to \ln2/2\approx0.3466 at endpoints; both equal 0 at p=0,1p=0,1 and G(0.5)=0.5G(0.5)=0.5, H(0.5)=1H(0.5)=1 so ratio =0.5=12=0.5=\tfrac12). The tightest constant is 12\tfrac12, achieved at p=12p=\tfrac12. (2)

(b) Parent: p=9/14p=9/14. H=914log2914514log2514=0.940H = -\frac{9}{14}\log_2\frac{9}{14} - \frac{5}{14}\log_2\frac{5}{14} = 0.940. (2) Weak (6/2): H=68log26828log228=0.811H = -\frac{6}{8}\log_2\frac68 - \frac28\log_2\frac28 = 0.811. Strong (3/3): H=1.000H = 1.000. (2) Weighted child =814(0.811)+614(1.000)=0.4634+0.4286=0.892= \frac{8}{14}(0.811) + \frac{6}{14}(1.000) = 0.4634 + 0.4286 = 0.892. Information gain =0.9400.892=0.048= 0.940 - 0.892 = 0.048. (2)

(c) Parent Gini =2914514=0.4592=2\cdot\frac{9}{14}\cdot\frac{5}{14}=0.4592. Weak Gini =26828=0.375=2\cdot\frac68\cdot\frac28=0.375; Strong Gini =21212=0.5=2\cdot\frac12\cdot\frac12=0.5. Weighted =814(0.375)+614(0.5)=0.2143+0.2143=0.4286=\frac{8}{14}(0.375)+\frac{6}{14}(0.5)=0.2143+0.2143=0.4286. Gini gain =0.45920.4286=0.0306>0=0.4592-0.4286=0.0306>0. (3) Both entropy gain (0.048>00.048>0) and Gini gain (0.031>00.031>0) are positive → they agree the split improves purity. (1)

(d) Entropy H(p)H(p) is concave (second derivative H(p)=1p(1p)ln2<0H''(p)=-\frac{1}{p(1-p)\ln2}<0). Splitting partitions the parent proportion pp as a convex combination p=kwkpkp=\sum_k w_k p_k with weights wk=Nk/Nw_k=N_k/N. By Jensen's inequality for concave HH: H(kwkpk)kwkH(pk)H(\sum_k w_k p_k) \ge \sum_k w_k H(p_k), i.e. parent entropy \ge weighted child entropy, so gain 0\ge 0. Equality iff all pkp_k equal. (4)


Question 2

(a) Probability a given sample is NOT chosen in one draw =11n=1-\frac1n. Over nn independent draws: (11n)n\left(1-\frac1n\right)^n. (3) Limit: limn(11n)n=e10.368\lim_{n\to\infty}\left(1-\frac1n\right)^n = e^{-1}\approx 0.368. Expected OOB fraction 36.8%\approx 36.8\% (so 63.2%\approx63.2\% in-bag). (2)

(b) αt=12ln1εtεt=12ln0.750.25=12ln3=0.5493\alpha_t=\tfrac12\ln\frac{1-\varepsilon_t}{\varepsilon_t}=\tfrac12\ln\frac{0.75}{0.25}=\tfrac12\ln 3=0.5493. (2) Update: wiwiexp(αtyiht(xi))w_i \leftarrow w_i\exp(-\alpha_t y_i h_t(x_i)). Correct (yiht=+1y_i h_t=+1): factor eαt=e0.5493=0.5774=1/3e^{-\alpha_t}=e^{-0.5493}=0.5774=1/\sqrt3. Misclassified (yiht=1y_i h_t=-1): factor e+αt=e0.5493=1.7321=3e^{+\alpha_t}=e^{0.5493}=1.7321=\sqrt3. (4)

(c) Zt=iwieαtyiht(xi)Z_t=\sum_i w_i e^{-\alpha_t y_i h_t(x_i)}. Split into correct (total weight 1εt1-\varepsilon_t) and wrong (εt\varepsilon_t): Zt=(1εt)eαt+εteαtZ_t=(1-\varepsilon_t)e^{-\alpha_t}+\varepsilon_t e^{\alpha_t}. Substitute eαt=(1εt)/εte^{\alpha_t}=\sqrt{(1-\varepsilon_t)/\varepsilon_t}: Zt=(1εt)εt1εt+εt1εtεt=εt(1εt)+εt(1εt)=2εt(1εt)Z_t=(1-\varepsilon_t)\sqrt{\tfrac{\varepsilon_t}{1-\varepsilon_t}}+\varepsilon_t\sqrt{\tfrac{1-\varepsilon_t}{\varepsilon_t}}=\sqrt{\varepsilon_t(1-\varepsilon_t)}+\sqrt{\varepsilon_t(1-\varepsilon_t)}=2\sqrt{\varepsilon_t(1-\varepsilon_t)}. (3) At εt=0.25\varepsilon_t=0.25: Zt=20.250.75=20.1875=0.8660Z_t=2\sqrt{0.25\cdot0.75}=2\sqrt{0.1875}=0.8660. (1) αt\alpha_t is chosen to minimize ZtZ_t (set dZt/dα=0dZ_t/d\alpha=0) because the training-error bound is tZt\prod_t Z_t; minimizing each ZtZ_t greedily tightens the bound → the exact αt\alpha_t formula. (2)

(d) Bagging averages many high-variance, low-bias trees → primarily reduces variance (decorrelated averaging). Boosting sequentially fits residuals/reweights → reduces bias (builds a strong learner from weak ones). Boosting overfits noisy labels because it up-weights persistently misclassified points; noisy/mislabeled points receive exploding weights and dominate later rounds. (5)


Question 3

(a) Difference ba=(3,4,0)b-a=(3,4,0). Euclidean =9+16+0=25=5=\sqrt{9+16+0}=\sqrt{25}=5. (2) Manhattan =3+4+0=7=|3|+|4|+0=7. (2) Cosine: ab=14+26+22=4+12+4=20a\cdot b=1\cdot4+2\cdot6+2\cdot2=4+12+4=20; a=1+4+4=3\|a\|=\sqrt{1+4+4}=3, b=16+36+4=56=7.4833\|b\|=\sqrt{16+36+4}=\sqrt{56}=7.4833. cosθ=20/(37.4833)=20/22.45=0.8909\cos\theta=20/(3\cdot7.4833)=20/22.45=0.8909; cosine distance =10.8909=0.1091=1-0.8909=0.1091. (2)

(b) Pseudocode: (3)

predict(x, X_train, y_train, K):
    dists = [ (euclid(x, X_train[i]), y_train[i]) for i in range(N) ]
    sort dists ascending by distance
    neighbours = first K entries
    votes = {}
    for (d, y) in neighbours:
        w = 1/(d + eps)
        votes[y] += w
    return argmax_c votes[c]

Complexity of one prediction: distance to all NN points costs O(ND)O(ND); selecting top-KK via sort O(NlogN)O(N\log N) or partial-select O(NlogK)O(N\log K). Total O(ND+NlogN)O(ND + N\log N). (2)

(c) =r1/D\ell=r^{1/D}, r=0.01r=0.01:

  • D=1D=1: =0.01\ell=0.01.
  • D=10D=10: =0.010.1=100.2=0.6310\ell=0.01^{0.1}=10^{-0.2}=0.6310.
  • D=100D=100: =0.010.01=100.02=0.9550\ell=0.01^{0.01}=10^{-0.02}=0.9550. (4) Interpretation: to capture just 1% of data in 100-D you must span 95.5% of each axis — "local" neighbourhoods are no longer local; all points become nearly equidistant, so distance-based ranking of neighbours loses meaning. To keep neighbourhoods local you'd need KK tiny (unreliable estimates) or huge NN. Hence KNN degrades badly in high dimensions; dimensionality reduction / feature selection is required. (3)
[
  {"claim":"Q1b information gain = 0.048","code":"import math\ndef H(a,b):\n    t=a+b; ps=[a/t,b/t]; return -sum(p*math.log2(p) for p in ps if p>0)\nparent=H(9,5); child=(8/14)*H(6,2)+(6/14)*H(3,3); gain=parent-child\nresult = round(gain,3)==0.048"},
  {"claim":"Q1c Gini gain approx 0.0306","code":"def G(a,b):\n    t=a+b; return 2*(a/t)*(b/t)\np=G(9,5); c=(8/14)*G(6,2)+(6/14)*G(3,3); result = round(p-c,4)==0.0306"},
  {"claim":"Q2b alpha = 0.5493 for eps=0.25","code":"import math\neps=0.25; alpha=0.5*math.log((1-eps)/eps); result = round(alpha,4)==0.5493"},
  {"claim":"Q2c Zt = 0.8660 for eps=0.25","code":"import math\neps=0.25; Z=2*math.sqrt(eps*(1-eps)); result = round(Z,4)==0.8660"},
  {"claim":"Q3a distances: euclid 5, manhattan 7, cosine dist 0.1091","code":"import math\na=[1,2,2]; b=[4,6,2]\neu=math.sqrt(sum((x-y)**2 for x,y in zip(a,b)))\nman=sum(abs(x-y) for x,y in zip(a,b))\ndot=sum(x*y for x,y in zip(a,b)); na=math.sqrt(sum(x*x for x in a)); nb=math.sqrt(sum(x*x for x in b))\ncd=1-dot/(na*nb)\nresult = eu==5 and man==7 and round(cd,4)==0.1091"},
  {"claim":"Q3c edge lengths r=0.01","code":"result = round(0.01**(1/10),4)==0.6310 and round(0.01**(1/100),4)==0.9550"}
]