Introduction
議題:用申請假釋者的屬性,預測他會不會違反假釋規定
學習重點:
- 設定隨機種子set.seed(),依比例分割資料
- 從邏輯式回歸的係數推算自變數的邊際效果
- 勝率和機率、勝率比和機率差 之間的換算
- 臨界機率對混淆矩陣(期望報酬)的影響payoff = matrix(c(0,-100,-10,-50),2,2); payoff
- AUC的實質意義payoff = matrix(c(100, -80, -20, 100),2,2); payoff
- 如何(從報酬矩陣)決定臨界機率
- 什麼是抽樣偏差,如何避免、如何修正
1 資料處理 Loading the Dataset
【1.1 讀進資料】How many parolees are contained in the dataset?
nrow(parole)
[1] 675
【1.2 底線機率】How many of the parolees in the dataset violated the terms of their parole?
sum(parole$violator==1)
[1] 78
2 整理資料框 Creating Our Prediction Model
【2.1 類別變數】Which variables in this dataset are unordered factors with at least three levels?
str(parole)
'data.frame': 675 obs. of 9 variables:
$ male : int 1 0 1 1 1 1 1 0 0 1 ...
$ race : int 1 1 2 1 2 2 1 1 1 2 ...
$ age : num 33.2 39.7 29.5 22.4 21.6 46.7 31 24.6 32.6 29.1 ...
$ state : int 1 1 1 1 1 1 1 1 1 1 ...
$ time.served : num 5.5 5.4 5.6 5.7 5.4 6 6 4.8 4.5 4.7 ...
$ max.sentence : int 18 12 12 18 12 18 18 12 13 12 ...
$ multiple.offenses: int 0 0 0 0 0 0 0 0 0 0 ...
$ crime : int 4 3 3 1 1 4 3 1 3 2 ...
$ violator : int 0 0 0 0 0 0 0 0 0 0 ...
【2.2 資料框摘要】How does the output of summary() change for a factor variable as compared to a numerical variable?
summary(parole)
male race age state
Min. :0.000 Min. :1.00 Min. :18.4 1:143
1st Qu.:1.000 1st Qu.:1.00 1st Qu.:25.4 2:120
Median :1.000 Median :1.00 Median :33.7 3: 82
Mean :0.807 Mean :1.42 Mean :34.5 4:330
3rd Qu.:1.000 3rd Qu.:2.00 3rd Qu.:42.5
Max. :1.000 Max. :2.00 Max. :67.0
time.served max.sentence multiple.offenses crime
Min. :0.00 Min. : 1.0 Min. :0.000 1:315
1st Qu.:3.25 1st Qu.:12.0 1st Qu.:0.000 2:106
Median :4.40 Median :12.0 Median :1.000 3:153
Mean :4.20 Mean :13.1 Mean :0.536 4:101
3rd Qu.:5.20 3rd Qu.:15.0 3rd Qu.:1.000
Max. :6.00 Max. :18.0 Max. :1.000
violator
Min. :0.000
1st Qu.:0.000
Median :0.000
Mean :0.116
3rd Qu.:0.000
Max. :1.000
3 資料分割 Splitting into a Training and Testing Set
【3.1 指定隨機種子、依比例分割資料】Roughly what proportion of parolees have been allocated to the training and testing sets?
set.seed(144)
library(caTools)
split = sample.split(parole$violator, SplitRatio = 0.7)
train = subset(parole, split == TRUE)
test = subset(parole, split == FALSE)
【3.2 隨機種子的功用】Now, suppose you re-ran lines [1]-[5] of Problem 3.1. What would you expect? If you instead ONLY re-ran lines [3]-[5], what would you expect? If you instead called set.seed() with a different number and then re-ran lines [3]-[5] of Problem 3.1, what would you expect?
# The exact same training/testing set split as the first execution of [1]-[5]
# A different training/testing set split from the first execution of [1]-[5]
# A different training/testing set split from the first execution of [1]-[5]
4 建立模型 Building a Logistic Regression Model
【4.1 顯著性】What variables are significant in this model?
model1 = glm(violator ~ .,data= train , family = "binomial")
summary(model1)
Call:
glm(formula = violator ~ ., family = "binomial", data = train)
Deviance Residuals:
Min 1Q Median 3Q Max
-1.704 -0.424 -0.272 -0.169 2.837
Coefficients:
Estimate Std. Error z value Pr(>|z|)
(Intercept) -4.241157 1.293885 -3.28 0.001 **
male 0.386990 0.437961 0.88 0.377
race 0.886719 0.395066 2.24 0.025 *
age -0.000176 0.016085 -0.01 0.991
state2 0.443301 0.481662 0.92 0.357
state3 0.834980 0.556270 1.50 0.133
state4 -3.396788 0.611586 -5.55 0.000000028 ***
time.served -0.123887 0.120423 -1.03 0.304
max.sentence 0.080295 0.055375 1.45 0.147
multiple.offenses 1.611992 0.385305 4.18 0.000028683 ***
crime2 0.683714 0.500355 1.37 0.172
crime3 -0.278105 0.432836 -0.64 0.521
crime4 -0.011763 0.571304 -0.02 0.984
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
(Dispersion parameter for binomial family taken to be 1)
Null deviance: 340.04 on 472 degrees of freedom
Residual deviance: 251.48 on 460 degrees of freedom
AIC: 277.5
Number of Fisher Scoring iterations: 6
- race , state4 , multiple.offenses
【4.2 從回歸係數估計邊際效用】What can we say based on the coefficient of the multiple.offenses variable?
exp(1.611992)
[1] 5.013
【4.3 從預測值估計勝率和機率】According to the model, what are the odds this individual is a violator? What is the probability this individual is a violator?
p
[1] 0.1544
5 驗證模型 Evaluating the Model on the Testing Set
【5.1 從測試資料預測機率】What is the maximum predicted probability of a violation?
Pred=predict(model1,type="response",test)
max(Pred)
[1] 0.9073
【5.2 從混淆矩陣計算敏感性、明確性、正確率】What is the model’s sensitivity, specificity, accuracy?
table(test$violator,Pred>0.5)
FALSE TRUE
0 167 12
1 11 12
12/(11+12)
[1] 0.5217
167/(167+12)
[1] 0.933
(167+12)/(167+12+11+12)
[1] 0.8861
【5.3 底線機率】What is the accuracy of a simple model that predicts that every parolee is a non-violator?
table(test$violator)
0 1
179 23
179/(179+23)
[1] 0.8861
【5.4 根據報償矩陣調整臨界機率】Which of the following most likely describes their preferences and best course of action?
- The board assigns more cost to a false negative than a false positive, and should therefore use a logistic regression cutoff less than 0.5.
【5.5 正確率 vs 辨識率】Which of the following is the most accurate assessment of the value of the logistic regression model with a cutoff 0.5 to a parole board, based on the model’s accuracy as compared to the simple baseline model?
- The model is likely of value to the board, and using a different logistic regression cutoff is likely to improve the model’s value.
【5.6 計算辨識率】Using the ROCR package, what is the AUC value for the model?
auc
[1] 0.7421
【5.7 辨識率的定義】Describe the meaning of AUC in this context.
- The probability the model can correctly differentiate between a randomly selected parole violator and a randomly selected parole non-violator.
6 抽樣偏差 Identifying Bias in Observational Data
【6.1 如何避免、診斷、修正抽樣偏差】How could we improve our dataset to best address selection bias?
- We should use a dataset tracking a group of parolees from the start of their parole until either they violated parole or they completed their term.
LS0tDQp0aXRsZTogIkFTMy0yIEdyb3VwLTQgUHJlZGljdGluZyBQYXJvbGUgVmlvbGF0b3JzIg0KYXV0aG9yOiAi546L5qyjIE0wNjQxMTEwMzkiDQpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sNCi0tLQ0KDQpgYGB7ciBlY2hvPVQsIG1lc3NhZ2U9RiwgY2FjaGU9Riwgd2FybmluZz1GfQ0Kcm0obGlzdD1scyhhbGw9VCkpDQpvcHRpb25zKGRpZ2l0cz00LCBzY2lwZW49MTIpDQpsaWJyYXJ5KG1hZ3JpdHRyKQ0KYGBgDQoNCi0gLSAtDQoNCiMjIyBJbnRyb2R1Y3Rpb24NCg0KKirorbDpoYzvvJrnlKjnlLPoq4vlgYfph4vogIXnmoTlsazmgKfvvIzpoJDmuKzku5bmnIPkuI3mnIPpgZXlj43lgYfph4vopo/lrpoqKg0KDQoqKuWtuOe/kumHjem7nu+8mioqDQoNCisg6Kit5a6a6Zqo5qmf56iu5a2Qc2V0LnNlZWQoKe+8jOS+neavlOS+i+WIhuWJsuizh+aWmQ0KKyDlvp7pgo/ovK/lvI/lm57mrbjnmoTkv4Lmlbjmjqjnrpfoh6rorormlbjnmoTpgorpmpvmlYjmnpwNCisg5Yud546H5ZKM5qmf546H44CB5Yud546H5q+U5ZKM5qmf546H5beuIOS5i+mWk+eahOaPm+eulyANCisg6Ieo55WM5qmf546H5bCN5re35reG55+p6ZmjKOacn+acm+WgsemFrCnnmoTlvbHpn79wYXlvZmYgPSBtYXRyaXgoYygwLC0xMDAsLTEwLC01MCksMiwyKTsgcGF5b2ZmDQorIEFVQ+eahOWvpuizquaEj+e+qXBheW9mZiA9IG1hdHJpeChjKDEwMCwgLTgwLCAtMjAsIDEwMCksMiwyKTsgcGF5b2ZmDQorIOWmguS9lSjlvp7loLHphaznn6npmaMp5rG65a6a6Ieo55WM5qmf546HIA0KKyDku4DpurzmmK/mir3mqKPlgY/lt64s5aaC5L2V6YG/5YWN44CB5aaC5L2V5L+u5q2jDQoNCjxicj4NCg0KLSAtIC0NCg0KIyMjIyAxIOizh+aWmeiZleeQhiBMb2FkaW5nIHRoZSBEYXRhc2V0DQoNCuOAkCoqMS4xIOiugOmAsuizh+aWmSoq44CRSG93IG1hbnkgcGFyb2xlZXMgYXJlIGNvbnRhaW5lZCBpbiB0aGUgZGF0YXNldD8NCmBgYHtyfQ0KDQpwYXJvbGUgPSByZWFkLmNzdigiQzovTUlUIHN1bW1lciAyMDE4L1VuaXQzL2RhdGEvcGFyb2xlLmNzdiIpDQpzdHIocGFyb2xlKQ0KbnJvdyhwYXJvbGUpDQpgYGANCg0K44CQKioxLjIg5bqV57ea5qmf546HKirjgJFIb3cgbWFueSBvZiB0aGUgcGFyb2xlZXMgaW4gdGhlIGRhdGFzZXQgdmlvbGF0ZWQgdGhlIHRlcm1zIG9mIHRoZWlyIHBhcm9sZT8NCmBgYHtyfQ0KDQpzdW0ocGFyb2xlJHZpb2xhdG9yPT0xKQ0KYGBgDQo8YnI+DQoNCi0gLSAtDQoNCiMjIyMgMiDmlbTnkIbos4fmlpnmoYYgQ3JlYXRpbmcgT3VyIFByZWRpY3Rpb24gTW9kZWwNCg0K44CQKioyLjEg6aGe5Yil6K6K5pW4KirjgJFXaGljaCB2YXJpYWJsZXMgaW4gdGhpcyBkYXRhc2V0IGFyZSB1bm9yZGVyZWQgZmFjdG9ycyB3aXRoIGF0IGxlYXN0IHRocmVlIGxldmVscz8gDQpgYGB7cn0NCg0Kc3RyKHBhcm9sZSkNCmBgYA0KKyBzdGF0ZSAsIGNyaW1lDQoNCuOAkCoqMi4yIOizh+aWmeahhuaRmOimgSoq44CRSG93IGRvZXMgdGhlIG91dHB1dCBvZiBgc3VtbWFyeSgpYCBjaGFuZ2UgZm9yIGEgZmFjdG9yIHZhcmlhYmxlIGFzIGNvbXBhcmVkIHRvIGEgbnVtZXJpY2FsIHZhcmlhYmxlPyANCmBgYHtyfQ0KcGFyb2xlJHN0YXRlID0gYXMuZmFjdG9yKHBhcm9sZSRzdGF0ZSkNCnBhcm9sZSRjcmltZSA9IGFzLmZhY3RvcihwYXJvbGUkY3JpbWUpDQpzdHIocGFyb2xlKQ0Kc3VtbWFyeShwYXJvbGUpDQpgYGANCjxicj4NCg0KLSAtIC0NCg0KIyMjIyAzIOizh+aWmeWIhuWJsiBTcGxpdHRpbmcgaW50byBhIFRyYWluaW5nIGFuZCBUZXN0aW5nIFNldA0KDQrjgJAqKjMuMSDmjIflrprpmqjmqZ/nqK7lrZDjgIHkvp3mr5TkvovliIblibLos4fmlpkqKuOAkVJvdWdobHkgd2hhdCBwcm9wb3J0aW9uIG9mIHBhcm9sZWVzIGhhdmUgYmVlbiBhbGxvY2F0ZWQgdG8gdGhlIHRyYWluaW5nIGFuZCB0ZXN0aW5nIHNldHM/DQpgYGB7cn0NCnNldC5zZWVkKDE0NCkNCmxpYnJhcnkoY2FUb29scykNCnNwbGl0ID0gc2FtcGxlLnNwbGl0KHBhcm9sZSR2aW9sYXRvciwgU3BsaXRSYXRpbyA9IDAuNykNCnRyYWluID0gc3Vic2V0KHBhcm9sZSwgc3BsaXQgPT0gVFJVRSkNCnRlc3QgPSBzdWJzZXQocGFyb2xlLCBzcGxpdCA9PSBGQUxTRSkNCmBgYA0KDQrjgJAqKjMuMiDpmqjmqZ/nqK7lrZDnmoTlip/nlKgqKuOAkU5vdywgc3VwcG9zZSB5b3UgcmUtcmFuIGxpbmVzIFsxXS1bNV0gb2YgUHJvYmxlbSAzLjEuIFdoYXQgd291bGQgeW91IGV4cGVjdD8gSWYgeW91IGluc3RlYWQgT05MWSByZS1yYW4gbGluZXMgWzNdLVs1XSwgd2hhdCB3b3VsZCB5b3UgZXhwZWN0PyBJZiB5b3UgaW5zdGVhZCBjYWxsZWQgc2V0LnNlZWQoKSB3aXRoIGEgZGlmZmVyZW50IG51bWJlciBhbmQgdGhlbiByZS1yYW4gbGluZXMgWzNdLVs1XSBvZiBQcm9ibGVtIDMuMSwgd2hhdCB3b3VsZCB5b3UgZXhwZWN0Pw0KYGBge3J9DQoNCiMgVGhlIGV4YWN0IHNhbWUgdHJhaW5pbmcvdGVzdGluZyBzZXQgc3BsaXQgYXMgdGhlIGZpcnN0IGV4ZWN1dGlvbiBvZiBbMV0tWzVdIA0KIyBBIGRpZmZlcmVudCB0cmFpbmluZy90ZXN0aW5nIHNldCBzcGxpdCBmcm9tIHRoZSBmaXJzdCBleGVjdXRpb24gb2YgWzFdLVs1XSANCiMgQSBkaWZmZXJlbnQgdHJhaW5pbmcvdGVzdGluZyBzZXQgc3BsaXQgZnJvbSB0aGUgZmlyc3QgZXhlY3V0aW9uIG9mIFsxXS1bNV0NCmBgYA0KPGJyPg0KDQotIC0gLQ0KDQojIyMjIDQg5bu656uL5qih5Z6LIEJ1aWxkaW5nIGEgTG9naXN0aWMgUmVncmVzc2lvbiBNb2RlbA0KDQrjgJAqKjQuMSDpoa/okZfmgKcqKuOAkVdoYXQgdmFyaWFibGVzIGFyZSBzaWduaWZpY2FudCBpbiB0aGlzIG1vZGVsPw0KYGBge3J9DQoNCm1vZGVsMSA9IGdsbSh2aW9sYXRvciB+IC4sZGF0YT0gdHJhaW4gLCBmYW1pbHkgPSAiYmlub21pYWwiKQ0Kc3VtbWFyeShtb2RlbDEpDQpgYGANCisgcmFjZSAsIHN0YXRlNCAsIG11bHRpcGxlLm9mZmVuc2VzIA0KDQrjgJAqKjQuMiDlvp7lm57mrbjkv4LmlbjkvLDoqIjpgorpmpvmlYjnlKgqKuOAkVdoYXQgY2FuIHdlIHNheSBiYXNlZCBvbiB0aGUgY29lZmZpY2llbnQgb2YgdGhlIGBtdWx0aXBsZS5vZmZlbnNlc2AgdmFyaWFibGU/DQpgYGB7cn0NCg0KZXhwKDEuNjExOTkyKQ0KIyBPdXIgbW9kZWwgcHJlZGljdHMgdGhhdCBhIHBhcm9sZWUgd2hvIGNvbW1pdHRlZCBtdWx0aXBsZSBvZmZlbnNlcyBoYXMgNS4wMSB0aW1lcyBoaWdoZXIgb2RkcyBvZiBiZWluZyBhIHZpb2xhdG9yIHRoYW4gYSBwYXJvbGVlIHdobyBkaWQgbm90IGNvbW1pdCBtdWx0aXBsZSBvZmZlbnNlcyBidXQgaXMgb3RoZXJ3aXNlIGlkZW50aWNhbC4NCmBgYA0KDQrjgJAqKjQuMyDlvp7poJDmuKzlgLzkvLDoqIjli53njoflkozmqZ/njocqKuOAkUFjY29yZGluZyB0byB0aGUgbW9kZWwsIHdoYXQgYXJlIHRoZSBvZGRzIHRoaXMgaW5kaXZpZHVhbCBpcyBhIHZpb2xhdG9yPyAgV2hhdCBpcyB0aGUgcHJvYmFiaWxpdHkgdGhpcyBpbmRpdmlkdWFsIGlzIGEgdmlvbGF0b3I/DQpgYGB7cn0NCg0KQyA9IGNvZWYobW9kZWwxKQ0KbmFtZXMocGFyb2xlKQ0KbG9naXQgPSBzdW0oQyAqIGMoMSwxLDEsNTAsMCwwLDAsMywxMiwwLDEsMCwwKSkNCm9kZHMgPSBleHAobG9naXQpDQpwID0gb2Rkcy8oMStvZGRzKQ0KDQpgYGANCjxicj4NCg0KLSAtIC0NCg0KIyMjIyA1IOmpl+itieaooeWeiyBFdmFsdWF0aW5nIHRoZSBNb2RlbCBvbiB0aGUgVGVzdGluZyBTZXQNCg0K44CQKio1LjEg5b6e5ris6Kmm6LOH5paZ6aCQ5ris5qmf546HKirjgJFXaGF0IGlzIHRoZSBtYXhpbXVtIHByZWRpY3RlZCBwcm9iYWJpbGl0eSBvZiBhIHZpb2xhdGlvbj8NCmBgYHtyfQ0KUHJlZD1wcmVkaWN0KG1vZGVsMSx0eXBlPSJyZXNwb25zZSIsdGVzdCkNCm1heChQcmVkKQ0KYGBgDQoNCuOAkCoqNS4yIOW+nua3t+a3huefqemZo+ioiOeul+aVj+aEn+aAp+OAgeaYjueiuuaAp+OAgeato+eiuueOhyoq44CRV2hhdCBpcyB0aGUgbW9kZWwncyBgc2Vuc2l0aXZpdHlgLCBgc3BlY2lmaWNpdHlgLCBgYWNjdXJhY3lgPw0KYGBge3J9DQp0YWJsZSh0ZXN0JHZpb2xhdG9yLFByZWQ+MC41KQ0KMTIvKDExKzEyKQ0KMTY3LygxNjcrMTIpDQooMTY3KzEyKS8oMTY3KzEyKzExKzEyKQ0KYGBgDQoNCuOAkCoqNS4zIOW6lee3muapn+eOhyoq44CRV2hhdCBpcyB0aGUgYWNjdXJhY3kgb2YgYSBzaW1wbGUgbW9kZWwgdGhhdCBwcmVkaWN0cyB0aGF0IGV2ZXJ5IHBhcm9sZWUgaXMgYSBub24tdmlvbGF0b3I/DQpgYGB7cn0NCnRhYmxlKHRlc3QkdmlvbGF0b3IpDQoxNzkvKDE3OSsyMykNCmBgYA0KDQrjgJAqKjUuNCDmoLnmk5rloLHlhJ/nn6npmaPoqr/mlbToh6jnlYzmqZ/njocqKuOAkVdoaWNoIG9mIHRoZSBmb2xsb3dpbmcgbW9zdCBsaWtlbHkgZGVzY3JpYmVzIHRoZWlyIHByZWZlcmVuY2VzIGFuZCBiZXN0IGNvdXJzZSBvZiBhY3Rpb24/DQoNCisgVGhlIGJvYXJkIGFzc2lnbnMgbW9yZSBjb3N0IHRvIGEgZmFsc2UgbmVnYXRpdmUgdGhhbiBhIGZhbHNlIHBvc2l0aXZlLCBhbmQgc2hvdWxkIHRoZXJlZm9yZSB1c2UgYSBsb2dpc3RpYyByZWdyZXNzaW9uIGN1dG9mZiBsZXNzIHRoYW4gMC41Lg0KDQoNCuOAkCoqNS41IOato+eiuueOhyB2cyDovqjorZjnjocqKuOAkVdoaWNoIG9mIHRoZSBmb2xsb3dpbmcgaXMgdGhlIG1vc3QgYWNjdXJhdGUgYXNzZXNzbWVudCBvZiB0aGUgdmFsdWUgb2YgdGhlIGxvZ2lzdGljIHJlZ3Jlc3Npb24gbW9kZWwgd2l0aCBhIGN1dG9mZiAwLjUgdG8gYSBwYXJvbGUgYm9hcmQsIGJhc2VkIG9uIHRoZSBtb2RlbCdzIGFjY3VyYWN5IGFzIGNvbXBhcmVkIHRvIHRoZSBzaW1wbGUgYmFzZWxpbmUgbW9kZWw/DQoNCisgVGhlIG1vZGVsIGlzIGxpa2VseSBvZiB2YWx1ZSB0byB0aGUgYm9hcmQsIGFuZCB1c2luZyBhIGRpZmZlcmVudCBsb2dpc3RpYyByZWdyZXNzaW9uIGN1dG9mZiBpcyBsaWtlbHkgdG8gaW1wcm92ZSB0aGUgbW9kZWwncyB2YWx1ZS4NCg0KDQrjgJAqKjUuNiDoqIjnrpfovqjorZjnjocqKuOAkVVzaW5nIHRoZSBgUk9DUmAgcGFja2FnZSwgd2hhdCBpcyB0aGUgQVVDIHZhbHVlIGZvciB0aGUgbW9kZWw/DQpgYGB7cn0NCmxpYnJhcnkoUk9DUikNClJPQ1JwcmVkVGVzdCA9IHByZWRpY3Rpb24oUHJlZCx0ZXN0JHZpb2xhdG9yKQ0KYXVjID0gYXMubnVtZXJpYyhwZXJmb3JtYW5jZShST0NScHJlZFRlc3QsICJhdWMiKUB5LnZhbHVlcykNCmF1Yw0KDQpgYGANCg0K44CQKio1Ljcg6L6o6K2Y546H55qE5a6a576pKirjgJFEZXNjcmliZSB0aGUgbWVhbmluZyBvZiBBVUMgaW4gdGhpcyBjb250ZXh0Lg0KDQorIFRoZSBwcm9iYWJpbGl0eSB0aGUgbW9kZWwgY2FuIGNvcnJlY3RseSBkaWZmZXJlbnRpYXRlIGJldHdlZW4gYSByYW5kb21seSBzZWxlY3RlZCBwYXJvbGUgdmlvbGF0b3IgYW5kIGEgcmFuZG9tbHkgc2VsZWN0ZWQgcGFyb2xlIG5vbi12aW9sYXRvci4NCg0KPGJyPg0KDQotIC0gLQ0KDQojIyMjIDYg5oq95qij5YGP5beuIElkZW50aWZ5aW5nIEJpYXMgaW4gT2JzZXJ2YXRpb25hbCBEYXRhDQoNCuOAkCoqNi4xIOWmguS9lemBv+WFjeOAgeiouuaWt+OAgeS/ruato+aKveaoo+WBj+W3rioq44CRSG93IGNvdWxkIHdlIGltcHJvdmUgb3VyIGRhdGFzZXQgdG8gYmVzdCBhZGRyZXNzIHNlbGVjdGlvbiBiaWFzPw0KDQorIFdlIHNob3VsZCB1c2UgYSBkYXRhc2V0IHRyYWNraW5nIGEgZ3JvdXAgb2YgcGFyb2xlZXMgZnJvbSB0aGUgc3RhcnQgb2YgdGhlaXIgcGFyb2xlIHVudGlsIGVpdGhlciB0aGV5IHZpb2xhdGVkIHBhcm9sZSBvciB0aGV5IGNvbXBsZXRlZCB0aGVpciB0ZXJtLiANCg0KPGJyPg0KDQotIC0gLQ0KDQo8YnI+PGJyPjxicj4NCg==