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?
parole= read.csv("Unit3/parole.csv")
#675
【1.2 底線機率】How many of the parolees in the dataset violated the terms of their parole?
table(parole$violator) #78
2 整理資料框 Creating Our Prediction Model
【2.1 類別變數】Which variables in this dataset are unordered factors with at least three levels?
#state, crime. 其他即使是factor,但都只有兩個層級
【2.2 資料框摘要】How does the output of summary() change for a factor variable as compared to a numerical variable?
parole$state= as.factor(parole$state)
parole$crime= as.factor(parole$crime)
summary(parole$state) #The output becomes similar to that of the table() function applied to that variable
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)
tr = subset(parole, split == TRUE)
ts = subset(parole, split == FALSE)
#70% to the training set, 30% to the testing set
【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?
#重新跑一次全部會得到一樣的結果。但設了隨機種子之後分割兩次會得不同結果。設不同隨機種子也會得不同結果。
4 建立模型 Building a Logistic Regression Model
【4.1 顯著性】What variables are significant in this model?
model1=glm(violator~., tr, family="binomial")
summary(model1)
#race2, state4, multiple.offenses1
【4.2 從回歸係數估計邊際效用】What can we say based on the coefficient of the multiple.offenses variable?
#For parolees A and B who are identical other than A having committed multiple offenses, the predicted log odds of A is 1.61 more than the predicted log odds of B. #有A和B兩個罪犯,除了A是多重犯罪者而B不是之外,兩者皆相同。而Coefficient=1.6119919的意思,代表A的logit會比B的高1.612。logit是機率,odds取log
#If we have a coefficient c for a variable, then that means the log odds (or Logit) are increased by c for a unit increase in the variable.
#so answer: Our model predicts that a parolee who committed multiple offenses has 5.01 times higher odds of being a violator than a parolee who did not commit multiple offenses but is otherwise identical.
【4.3 從預測值估計勝率和機率】Consider a parolee who is male, of white race, aged 50 years at prison release, from the state of Maryland, served 3 months, had a maximum sentence of 12 months, did not commit multiple offenses, and committed a larceny. Answer the following questions based on the model’s predictions for this individual. According to the model, what are the odds this individual is a violator? What is the probability this individual is a violator?
#male 0.3869904
#race 0.8867192
#age -0.0001756
#time.served -0.1238867
#max.sentence 0.0802954
#crime2 0.6837143
A= -4.2411574+0.3869904*1+ 0.8867192*1+ 50*-0.0001756+ 3*-0.1238867 + 12*0.0802954+ 1*0.6837143 #logit
#odd= p/(1-p),p = odd/(1+odd)#導一下可求出
A ; exp(A)/(1+exp(A))
#所以預測此人假釋再犯罪的odd為-1.700629,而機率則為0.1543832
5 驗證模型 Evaluating the Model on the Testing Set
【5.1 從測試資料預測機率】What is the maximum predicted probability of a violation?
pred1=predict(model1, newdata=ts, type="response")
summary(pred1)
#0.9073
【5.2 從混淆矩陣計算敏感性、明確性、正確率】What is the model’s sensitivity, specificity, accuracy?
table(ts$violator, as.numeric(pred1 >= 0.5)) #做出confusion matrix
sens= 12/(12+11)
spec= 167/(167+12)
ACC= (167+12)/(167+12+11+12)
sens;spec;ACC
【5.3 底線機率】What is the accuracy of a simple model that predicts that every parolee is a non-violator?
table(ts$violator)
179/(179+23)
【5.4 根據報償矩陣調整臨界機率】Which of the following most likely describes their preferences and best course of action?
table(ts$violator, as.numeric(pred1 <= 0.5))
#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.
#縮減臨界機率會導致positive預測增加,所以FP也會比較多,並且減少FN。
【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?
table(ts$violator, as.numeric(pred1 >= 0.5))
#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?
library(ROCR)
ROCRpred1= prediction(pred1, ts$violator)
as.numeric(performance(ROCRpred1, "auc") @y.values)
#AUC模型在所有臨界機率之中的辨識能力;在樣本的兩類別中各隨機選取一點時,模型能夠正確區辨它們的機率
【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.
LS0tDQp0aXRsZTogIkFTMy0yIFByZWRpY3RpbmcgUGFyb2xlIFZpb2xhdG9ycyINCmF1dGhvcjogIuWNk+mbjeeEtiBEOTk0MDEwMDAxIg0Kb3V0cHV0OiBodG1sX25vdGVib29rDQotLS0NCg0KYGBge3IgZWNobz1ULCBtZXNzYWdlPUYsIGNhY2hlPUYsIHdhcm5pbmc9Rn0NCnJtKGxpc3Q9bHMoYWxsPVQpKQ0Kb3B0aW9ucyhkaWdpdHM9NCwgc2NpcGVuPTEyKQ0KbGlicmFyeShtYWdyaXR0cikNCmBgYA0KDQotIC0gLQ0KDQojIyMgSW50cm9kdWN0aW9uDQoNCioq6K2w6aGM77ya55So55Sz6KuL5YGH6YeL6ICF55qE5bGs5oCn77yM6aCQ5ris5LuW5pyD5LiN5pyD6YGV5Y+N5YGH6YeL6KaP5a6aKioNCg0KKirlrbjnv5Lph43pu57vvJoqKg0KDQorIOioreWumumaqOapn+eoruWtkHNldC5zZWVkKCnvvIzkvp3mr5TkvovliIblibLos4fmlpkNCisg5b6e6YKP6Lyv5byP5Zue5q2455qE5L+C5pW45o6o566X6Ieq6K6K5pW455qE6YKK6Zqb5pWI5p6cDQorIOWLneeOh+WSjOapn+eOh+OAgeWLneeOh+avlOWSjOapn+eOh+W3riDkuYvplpPnmoTmj5vnrpcgDQorIOiHqOeVjOapn+eOh+Wwjea3t+a3huefqemZoyjmnJ/mnJvloLHphawp55qE5b2x6Z+/cGF5b2ZmID0gbWF0cml4KGMoMCwtMTAwLC0xMCwtNTApLDIsMik7IHBheW9mZg0KKyBBVUPnmoTlr6bos6rmhI/nvqlwYXlvZmYgPSBtYXRyaXgoYygxMDAsIC04MCwgLTIwLCAxMDApLDIsMik7IHBheW9mZg0KKyDlpoLkvZUo5b6e5aCx6YWs55+p6ZmjKeaxuuWumuiHqOeVjOapn+eOhyANCisg5LuA6bq85piv5oq95qij5YGP5beuLOWmguS9lemBv+WFjeOAgeWmguS9leS/ruatow0KDQo8YnI+DQoNCi0gLSAtDQoNCiMjIyMgMSDos4fmlpnomZXnkIYgTG9hZGluZyB0aGUgRGF0YXNldA0KDQrjgJAqKjEuMSDoroDpgLLos4fmlpkqKuOAkUhvdyBtYW55IHBhcm9sZWVzIGFyZSBjb250YWluZWQgaW4gdGhlIGRhdGFzZXQ/DQpgYGB7cn0NCnBhcm9sZT0gcmVhZC5jc3YoIlVuaXQzL3Bhcm9sZS5jc3YiKQ0KIzY3NQ0KYGBgDQoNCuOAkCoqMS4yIOW6lee3muapn+eOhyoq44CRSG93IG1hbnkgb2YgdGhlIHBhcm9sZWVzIGluIHRoZSBkYXRhc2V0IHZpb2xhdGVkIHRoZSB0ZXJtcyBvZiB0aGVpciBwYXJvbGU/DQpgYGB7cn0NCnRhYmxlKHBhcm9sZSR2aW9sYXRvcikgIzc4DQpgYGANCjxicj4NCg0KLSAtIC0NCg0KIyMjIyAyIOaVtOeQhuizh+aWmeahhiBDcmVhdGluZyBPdXIgUHJlZGljdGlvbiBNb2RlbA0KDQrjgJAqKjIuMSDpoZ7liKXorormlbgqKuOAkVdoaWNoIHZhcmlhYmxlcyBpbiB0aGlzIGRhdGFzZXQgYXJlIHVub3JkZXJlZCBmYWN0b3JzIHdpdGggYXQgbGVhc3QgdGhyZWUgbGV2ZWxzPyANCmBgYHtyfQ0KI3N0YXRlLCBjcmltZS4g5YW25LuW5Y2z5L2/5pivZmFjdG9y77yM5L2G6YO95Y+q5pyJ5YWp5YCL5bGk57SaDQpgYGANCg0K44CQKioyLjIg6LOH5paZ5qGG5pGY6KaBKirjgJFIb3cgZG9lcyB0aGUgb3V0cHV0IG9mIGBzdW1tYXJ5KClgIGNoYW5nZSBmb3IgYSBmYWN0b3IgdmFyaWFibGUgYXMgY29tcGFyZWQgdG8gYSBudW1lcmljYWwgdmFyaWFibGU/IA0KYGBge3J9DQpwYXJvbGUkc3RhdGU9IGFzLmZhY3RvcihwYXJvbGUkc3RhdGUpDQpwYXJvbGUkY3JpbWU9IGFzLmZhY3RvcihwYXJvbGUkY3JpbWUpDQpzdW1tYXJ5KHBhcm9sZSRzdGF0ZSkgI1RoZSBvdXRwdXQgYmVjb21lcyBzaW1pbGFyIHRvIHRoYXQgb2YgdGhlIHRhYmxlKCkgZnVuY3Rpb24gYXBwbGllZCB0byB0aGF0IHZhcmlhYmxlDQpgYGANCjxicj4NCg0KLSAtIC0NCg0KIyMjIyAzIOizh+aWmeWIhuWJsiBTcGxpdHRpbmcgaW50byBhIFRyYWluaW5nIGFuZCBUZXN0aW5nIFNldA0KDQrjgJAqKjMuMSDmjIflrprpmqjmqZ/nqK7lrZDjgIHkvp3mr5TkvovliIblibLos4fmlpkqKuOAkVJvdWdobHkgd2hhdCBwcm9wb3J0aW9uIG9mIHBhcm9sZWVzIGhhdmUgYmVlbiBhbGxvY2F0ZWQgdG8gdGhlIHRyYWluaW5nIGFuZCB0ZXN0aW5nIHNldHM/DQpgYGB7cn0NCiBzZXQuc2VlZCgxNDQpICPoqK3lrprpmqjmqZ/nqK7lrZANCiBsaWJyYXJ5KGNhVG9vbHMpIA0KIHNwbGl0ID0gc2FtcGxlLnNwbGl0KHBhcm9sZSR2aW9sYXRvciwgU3BsaXRSYXRpbyA9IDAuNykNCiB0ciA9IHN1YnNldChwYXJvbGUsIHNwbGl0ID09IFRSVUUpDQogdHMgPSBzdWJzZXQocGFyb2xlLCBzcGxpdCA9PSBGQUxTRSkNCiAjNzAlIHRvIHRoZSB0cmFpbmluZyBzZXQsIDMwJSB0byB0aGUgdGVzdGluZyBzZXQNCmBgYA0KDQrjgJAqKjMuMiDpmqjmqZ/nqK7lrZDnmoTlip/nlKgqKuOAkU5vdywgc3VwcG9zZSB5b3UgcmUtcmFuIGxpbmVzIFsxXS1bNV0gb2YgUHJvYmxlbSAzLjEuIFdoYXQgd291bGQgeW91IGV4cGVjdD8gSWYgeW91IGluc3RlYWQgT05MWSByZS1yYW4gbGluZXMgWzNdLVs1XSwgd2hhdCB3b3VsZCB5b3UgZXhwZWN0PyBJZiB5b3UgaW5zdGVhZCBjYWxsZWQgc2V0LnNlZWQoKSB3aXRoIGEgZGlmZmVyZW50IG51bWJlciBhbmQgdGhlbiByZS1yYW4gbGluZXMgWzNdLVs1XSBvZiBQcm9ibGVtIDMuMSwgd2hhdCB3b3VsZCB5b3UgZXhwZWN0Pw0KYGBge3J9DQoj6YeN5paw6LeR5LiA5qyh5YWo6YOo5pyD5b6X5Yiw5LiA5qij55qE57WQ5p6c44CC5L2G6Kit5LqG6Zqo5qmf56iu5a2Q5LmL5b6M5YiG5Ymy5YWp5qyh5pyD5b6X5LiN5ZCM57WQ5p6c44CC6Kit5LiN5ZCM6Zqo5qmf56iu5a2Q5Lmf5pyD5b6X5LiN5ZCM57WQ5p6c44CCDQpgYGANCjxicj4NCg0KLSAtIC0NCg0KIyMjIyA0IOW7uueri+aooeWeiyBCdWlsZGluZyBhIExvZ2lzdGljIFJlZ3Jlc3Npb24gTW9kZWwNCg0K44CQKio0LjEg6aGv6JGX5oCnKirjgJFXaGF0IHZhcmlhYmxlcyBhcmUgc2lnbmlmaWNhbnQgaW4gdGhpcyBtb2RlbD8NCmBgYHtyfQ0KbW9kZWwxPWdsbSh2aW9sYXRvcn4uLCB0ciwgIGZhbWlseT0iYmlub21pYWwiKQ0Kc3VtbWFyeShtb2RlbDEpDQojcmFjZTIsIHN0YXRlNCwgbXVsdGlwbGUub2ZmZW5zZXMxDQpgYGANCg0K44CQKioqNC4yIOW+nuWbnuatuOS/guaVuOS8sOioiOmCiumam+aViOeUqCoqKuOAkVdoYXQgY2FuIHdlIHNheSBiYXNlZCBvbiB0aGUgY29lZmZpY2llbnQgb2YgdGhlIGBtdWx0aXBsZS5vZmZlbnNlc2AgdmFyaWFibGU/DQpgYGB7cn0NCiNGb3IgcGFyb2xlZXMgQSBhbmQgQiB3aG8gYXJlIGlkZW50aWNhbCBvdGhlciB0aGFuIEEgaGF2aW5nIGNvbW1pdHRlZCBtdWx0aXBsZSBvZmZlbnNlcywgdGhlIHByZWRpY3RlZCBsb2cgb2RkcyBvZiBBIGlzIDEuNjEgbW9yZSB0aGFuIHRoZSBwcmVkaWN0ZWQgbG9nIG9kZHMgb2YgQi4gI+aciUHlkoxC5YWp5YCL572q54qv77yM6Zmk5LqGQeaYr+WkmumHjeeKr+e9quiAheiAjELkuI3mmK/kuYvlpJbvvIzlhanogIXnmobnm7jlkIzjgILogIxDb2VmZmljaWVudD0xLjYxMTk5MTnnmoTmhI/mgJ3vvIzku6PooahB55qEbG9naXTmnIPmr5RC55qE6auYMS42MTLjgIJsb2dpdOaYr+apn+eOh++8jG9kZHPlj5Zsb2cNCiNJZiB3ZSBoYXZlIGEgY29lZmZpY2llbnQgYyBmb3IgYSB2YXJpYWJsZSwgdGhlbiB0aGF0IG1lYW5zIHRoZSBsb2cgb2RkcyAob3IgTG9naXQpIGFyZSBpbmNyZWFzZWQgYnkgYyBmb3IgYSB1bml0IGluY3JlYXNlIGluIHRoZSB2YXJpYWJsZS4NCiNzbyBhbnN3ZXI6IE91ciBtb2RlbCBwcmVkaWN0cyB0aGF0IGEgcGFyb2xlZSB3aG8gY29tbWl0dGVkIG11bHRpcGxlIG9mZmVuc2VzIGhhcyA1LjAxIHRpbWVzIGhpZ2hlciBvZGRzIG9mIGJlaW5nIGEgdmlvbGF0b3IgdGhhbiBhIHBhcm9sZWUgd2hvIGRpZCBub3QgY29tbWl0IG11bHRpcGxlIG9mZmVuc2VzIGJ1dCBpcyBvdGhlcndpc2UgaWRlbnRpY2FsLg0KYGBgDQoNCuOAkCoqNC4zIOW+numgkOa4rOWAvOS8sOioiOWLneeOh+WSjOapn+eOhyoq44CRQ29uc2lkZXIgYSBwYXJvbGVlIHdobyBpcyBtYWxlLCBvZiB3aGl0ZSByYWNlLCBhZ2VkIDUwIHllYXJzIGF0IHByaXNvbiByZWxlYXNlLCBmcm9tIHRoZSBzdGF0ZSBvZiBNYXJ5bGFuZCwgc2VydmVkIDMgbW9udGhzLCBoYWQgYSBtYXhpbXVtIHNlbnRlbmNlIG9mIDEyIG1vbnRocywgZGlkIG5vdCBjb21taXQgbXVsdGlwbGUgb2ZmZW5zZXMsIGFuZCBjb21taXR0ZWQgYSBsYXJjZW55LiBBbnN3ZXIgdGhlIGZvbGxvd2luZyBxdWVzdGlvbnMgYmFzZWQgb24gdGhlIG1vZGVsJ3MgcHJlZGljdGlvbnMgZm9yIHRoaXMgaW5kaXZpZHVhbC4NCkFjY29yZGluZyB0byB0aGUgbW9kZWwsIHdoYXQgYXJlIHRoZSBvZGRzIHRoaXMgaW5kaXZpZHVhbCBpcyBhIHZpb2xhdG9yPyAgV2hhdCBpcyB0aGUgcHJvYmFiaWxpdHkgdGhpcyBpbmRpdmlkdWFsIGlzIGEgdmlvbGF0b3I/DQpgYGB7cn0NCiNtYWxlIDAuMzg2OTkwNA0KI3JhY2UgMC44ODY3MTkyDQojYWdlIC0wLjAwMDE3NTYNCiN0aW1lLnNlcnZlZCAtMC4xMjM4ODY3DQojbWF4LnNlbnRlbmNlIDAuMDgwMjk1NA0KI2NyaW1lMiAwLjY4MzcxNDMNCkE9IC00LjI0MTE1NzQrMC4zODY5OTA0KjErIDAuODg2NzE5MioxKyA1MCotMC4wMDAxNzU2KyAzKi0wLjEyMzg4NjcgKyAxMiowLjA4MDI5NTQrIDEqMC42ODM3MTQzICNsb2dpdA0KI29kZD0gcC8oMS1wKSxwID0gb2RkLygxK29kZCkj5bCO5LiA5LiL5Y+v5rGC5Ye6DQpBIDsgZXhwKEEpLygxK2V4cChBKSkNCiPmiYDku6XpoJDmuKzmraTkurrlgYfph4vlho3niq/nvarnmoRvZGTngrotMS43MDA2MjnvvIzogIzmqZ/njofliYfngrowLjE1NDM4MzINCg0KDQpgYGANCjxicj4NCg0KLSAtIC0NCg0KIyMjIyA1IOmpl+itieaooeWeiyBFdmFsdWF0aW5nIHRoZSBNb2RlbCBvbiB0aGUgVGVzdGluZyBTZXQNCg0K44CQKio1LjEg5b6e5ris6Kmm6LOH5paZ6aCQ5ris5qmf546HKirjgJFXaGF0IGlzIHRoZSBtYXhpbXVtIHByZWRpY3RlZCBwcm9iYWJpbGl0eSBvZiBhIHZpb2xhdGlvbj8NCmBgYHtyfQ0KcHJlZDE9cHJlZGljdChtb2RlbDEsIG5ld2RhdGE9dHMsIHR5cGU9InJlc3BvbnNlIikNCnN1bW1hcnkocHJlZDEpDQojMC45MDczDQpgYGANCg0K44CQKio1LjIg5b6e5re35reG55+p6Zmj6KiI566X5pWP5oSf5oCn44CB5piO56K65oCn44CB5q2j56K6546HKirjgJFXaGF0IGlzIHRoZSBtb2RlbCdzIGBzZW5zaXRpdml0eWAsIGBzcGVjaWZpY2l0eWAsIGBhY2N1cmFjeWA/DQpgYGB7cn0NCnRhYmxlKHRzJHZpb2xhdG9yLCBhcy5udW1lcmljKHByZWQxID49IDAuNSkpICPlgZrlh7pjb25mdXNpb24gbWF0cml4DQpzZW5zPSAxMi8oMTIrMTEpDQpzcGVjPSAxNjcvKDE2NysxMikNCkFDQz0gKDE2NysxMikvKDE2NysxMisxMSsxMikNCnNlbnM7c3BlYztBQ0MNCmBgYA0KDQrjgJAqKjUuMyDlupXnt5rmqZ/njocqKuOAkVdoYXQgaXMgdGhlIGFjY3VyYWN5IG9mIGEgc2ltcGxlIG1vZGVsIHRoYXQgcHJlZGljdHMgdGhhdCBldmVyeSBwYXJvbGVlIGlzIGEgbm9uLXZpb2xhdG9yPw0KYGBge3J9DQp0YWJsZSh0cyR2aW9sYXRvcikNCjE3OS8oMTc5KzIzKQ0KYGBgDQoNCuOAkCoqNS40IOagueaTmuWgseWEn+efqemZo+iqv+aVtOiHqOeVjOapn+eOhyoq44CRV2hpY2ggb2YgdGhlIGZvbGxvd2luZyBtb3N0IGxpa2VseSBkZXNjcmliZXMgdGhlaXIgcHJlZmVyZW5jZXMgYW5kIGJlc3QgY291cnNlIG9mIGFjdGlvbj8NCmBgYHtyfQ0KdGFibGUodHMkdmlvbGF0b3IsIGFzLm51bWVyaWMocHJlZDEgPD0gMC41KSkNCiNUaGUgYm9hcmQgYXNzaWducyBtb3JlIGNvc3QgdG8gYSBmYWxzZSBuZWdhdGl2ZSB0aGFuIGEgZmFsc2UgcG9zaXRpdmUsIGFuZCBzaG91bGQgdGhlcmVmb3JlIHVzZSBhIGxvZ2lzdGljIHJlZ3Jlc3Npb24gY3V0b2ZmIGxlc3MgdGhhbiAwLjUuDQoj57iu5rib6Ieo55WM5qmf546H5pyD5bCO6Ie0cG9zaXRpdmXpoJDmuKzlop7liqDvvIzmiYDku6VGUOS5n+acg+avlOi8g+Wkmu+8jOS4puS4lOa4m+WwkUZO44CCDQpgYGANCg0K44CQKio1LjUg5q2j56K6546HIHZzIOi+qOitmOeOhyoq44CRV2hpY2ggb2YgdGhlIGZvbGxvd2luZyBpcyB0aGUgbW9zdCBhY2N1cmF0ZSBhc3Nlc3NtZW50IG9mIHRoZSB2YWx1ZSBvZiB0aGUgbG9naXN0aWMgcmVncmVzc2lvbiBtb2RlbCB3aXRoIGEgY3V0b2ZmIDAuNSB0byBhIHBhcm9sZSBib2FyZCwgYmFzZWQgb24gdGhlIG1vZGVsJ3MgYWNjdXJhY3kgYXMgY29tcGFyZWQgdG8gdGhlIHNpbXBsZSBiYXNlbGluZSBtb2RlbD8NCmBgYHtyfQ0KdGFibGUodHMkdmlvbGF0b3IsIGFzLm51bWVyaWMocHJlZDEgPj0gMC41KSkNCiNUaGUgbW9kZWwgaXMgbGlrZWx5IG9mIHZhbHVlIHRvIHRoZSBib2FyZCwgYW5kIHVzaW5nIGEgZGlmZmVyZW50IGxvZ2lzdGljIHJlZ3Jlc3Npb24gY3V0b2ZmIGlzIGxpa2VseSB0byBpbXByb3ZlIHRoZSBtb2RlbCdzIHZhbHVlLg0KYGBgDQoNCuOAkCoqNS42IOioiOeul+i+qOitmOeOhyoq44CRVXNpbmcgdGhlIGBST0NSYCBwYWNrYWdlLCB3aGF0IGlzIHRoZSBBVUMgdmFsdWUgZm9yIHRoZSBtb2RlbD8NCmBgYHtyfQ0KbGlicmFyeShST0NSKQ0KUk9DUnByZWQxPSBwcmVkaWN0aW9uKHByZWQxLCB0cyR2aW9sYXRvcikNCmFzLm51bWVyaWMocGVyZm9ybWFuY2UoUk9DUnByZWQxLCAiYXVjIikgQHkudmFsdWVzKQ0KI0FVQ+aooeWei+WcqOaJgOacieiHqOeVjOapn+eOh+S5i+S4reeahOi+qOitmOiDveWKm++8m+WcqOaoo+acrOeahOWFqemhnuWIpeS4reWQhOmaqOapn+mBuOWPluS4gOm7nuaZgu+8jOaooeWei+iDveWkoOato+eiuuWNgOi+qOWug+WAkeeahOapn+eOhw0KYGBgDQoNCuOAkCoqNS43IOi+qOitmOeOh+eahOWumue+qSoq44CRRGVzY3JpYmUgdGhlIG1lYW5pbmcgb2YgQVVDIGluIHRoaXMgY29udGV4dC4NCmBgYHtyfQ0KI1RoZSBwcm9iYWJpbGl0eSB0aGUgbW9kZWwgY2FuIGNvcnJlY3RseSBkaWZmZXJlbnRpYXRlIGJldHdlZW4gYSByYW5kb21seSBzZWxlY3RlZCBwYXJvbGUgdmlvbGF0b3IgYW5kIGEgcmFuZG9tbHkgc2VsZWN0ZWQgcGFyb2xlIG5vbi12aW9sYXRvcg0KYGBgDQo8YnI+DQoNCi0gLSAtDQoNCiMjIyMgNiDmir3mqKPlgY/lt64gSWRlbnRpZnlpbmcgQmlhcyBpbiBPYnNlcnZhdGlvbmFsIERhdGENCg0K44CQKio2LjEg5aaC5L2V6YG/5YWN44CB6Ki65pa344CB5L+u5q2j5oq95qij5YGP5beuKirjgJFIb3cgY291bGQgd2UgaW1wcm92ZSBvdXIgZGF0YXNldCB0byBiZXN0IGFkZHJlc3Mgc2VsZWN0aW9uIGJpYXM/DQpgYGB7cn0NCiNXZSBzaG91bGQgdXNlIGEgZGF0YXNldCB0cmFja2luZyBhIGdyb3VwIG9mIHBhcm9sZWVzIGZyb20gdGhlIHN0YXJ0IG9mIHRoZWlyIHBhcm9sZSB1bnRpbCBlaXRoZXIgdGhleSB2aW9sYXRlZCBwYXJvbGUgb3IgdGhleSBjb21wbGV0ZWQgdGhlaXIgdGVybS4NCmBgYA0KPGJyPg0KDQotIC0gLQ0KDQo8YnI+PGJyPjxicj4NCg==