MNIST 데이터(우편번호)로 classification을 연습해보자.

데이터 살펴보기

변수개수 & 관측치 개수

dim(mnist.train) ; dim(mnist.test) ;range(mnist.train[,-1])
[1] 60000   785
[1] 10000   785
[1] 0 1
  • 각각 785개의 변수로 구성되었다.
  • 각 변수는 이미지의 픽셀을 의미하며, 변수값은 픽셀의 명도를 나타낸다.
  • 픽셀의 명도는 0~1 사이의 값을 가진다.


- training set은 6만건의 데이터로 이루어져있고, - test set은 만건의 데이터로 이루어져있다.

결측값 확인

sum(is.na(mnist.train)) ;sum(is.na(mnist.test))
[1] 0
[1] 0
  • 결측값은 하나도 없다. 그럼 기분좋게 분석을 시작해보도록 하자!

Knn (with LOOCV)

error.list
 [1] 0.0309 0.0309 0.0309 0.0309 0.0309 0.0309 0.0309 0.0309 0.0309 0.0309
mean(predict.knn[[1]]== as.factor(mnist.test[,1])) #accuracy rate
[1] 0.9691
table(predict.knn[[1]], as.factor(mnist.test[,1]))
   
       0    1    2    3    4    5    6    7    8    9
  0  973    0    7    0    0    1    4    0    6    2
  1    1 1129    6    1    7    1    2   14    1    5
  2    1    3  992    2    0    0    0    6    3    1
  3    0    0    5  970    0   12    0    2   14    6
  4    0    1    1    1  944    2    3    4    5   10
  5    1    1    0   19    0  860    5    0   13    5
  6    3    1    2    0    3    5  944    0    3    1
  7    1    0   16    7    5    1    0  992    4   11
  8    0    0    3    7    1    6    0    0  920    1
  9    0    0    0    3   22    4    0   10    5  967

랜덤포레스트로 넘어가보자.


randomforest

rf.h

Call:
 randomForest(formula = as.factor(y) ~ ., data = mnist.train,      mtry = 28, importance = T) 
               Type of random forest: classification
                     Number of trees: 500
No. of variables tried at each split: 28

        OOB estimate of  error rate: 2.96%
Confusion matrix:
     0    1    2    3    4    5    6    7    8    9 class.error
0 5852    1    6    2    5    4   16    2   31    4  0.01198717
1    1 6648   33    9   12    4    5   12   12    6  0.01394245
2   24   10 5795   17   19    2   17   31   36    7  0.02735817
3    7    5   74 5868    1   43    7   45   53   28  0.04289675
4    9   10   11    0 5679    0   22   11   12   88  0.02790140
5   18    6   10   55    8 5227   42    4   32   19  0.03578676
6   20    8    3    0   10   28 5831    0   18    0  0.01470091
7    6   20   50    4   36    1    0 6069   12   67  0.03128492
8   10   28   31   42   25   32   28    4 5589   62  0.04477867
9   22   10   10   72   61   17    4   45   40 5668  0.04723483

오류를 줄이고 싶다면, 3,8,9를 잘 구분할 수 있도록 학습 시키는 것이 중요하겠다.

mean(yhat.rf!=mnist.test$y); mean(yhat.rf==mnist.test$y)
[1] 0.0288
[1] 0.9712


variance importance plot

# 가장 많은 영향을 주는 변수 상위 10개를 골랐다. 
head(order(tmp$MeanDecreaseAccuracy, decreasing=T), n=10)
 [1] 294 297 322 325 321 295 298 269 349 575
head(order(tmp$MeanDecreaseGini, decreasing=T), n=10)
 [1] 379 407 351 410 378 212 462 406 434 156
  • 어떤 변수가 중요한 영향을 미치는지 살펴보았는데, 현 데이터에서는 큰 의미가 없는 것 같다.
  • 이미지 데이터에서는 변수가 중요한 의미를 가지지 않기 때문이다…..

마지막으로 boosting을 해보자.


Boosting

result.boosting
Call:
maboost(mnist.train[, -1], y = as.factor(mnist.train$y))

Loss: Method: normal   Iteration: 100 

Final Confusion Matrix for Data:
   g
       0    1    2    3    4    5    6    7    8    9
  0 5515    0   26   20   13  147   52    7  128   15
  1    1 6446   57   30    5   26   10   13  129   25
  2   44   65 5121   97  123   54  104  114  205   31
  3   28   56  179 5150   18  267   27   57  211  138
  4   16   15   32   11 5158    6   59   17   64  464
  5   52   49   50  301   90 4544   76   22  112  125
  6   58   38  127    6  112  134 5376    7   58    2
  7   14   81   91    6  114   12    0 5497   60  390
  8   15   93   59  260   47  135   43   14 4988  197
  9   36   19   40   97  239   26    6  141  102 5243

Train Error: 0.116 

Out-Of-Bag Error:  0.127  iteration= 100 

Additional Estimates of number of iterations:

train.err1 train.kap1 
        99         99 
mean(result.boosting$fit == mnist.train$y) #accuracy
[1] 0.8839667

Summary

Acc error ET Remarks
Knn 0.97 0.031 19h 계산시간 너무 오래 걸림
RF 0.97 0.029 6h boosting보다 짧은 계신시간에 비슷한 정확도
Boosting 0.88 0.116 2h 계산시간 매우 짧으나, 정확도가 너무 낮아서 아쉬움

Warning message:
In strsplit(code, "\n", fixed = TRUE) :
  input string 1 is invalid in this locale

끝!!!

LS0tDQp0aXRsZTogIkRhdGEgbWluaW5nIEhXNCAoUmV2aXNlZCB2ZXIuKSINCkF1dGhvcjogIlllcmltIExpbSINCkRhdGU6ICIyMDE464WEIDbsm5QgMuydvCINCm91dHB1dDogDQogIGh0bWxfbm90ZWJvb2s6DQogICAgdG9jOiB0cnVlDQotLS0NCg0KPiBNTklTVCDrjbDsnbTthLAo7Jqw7Y6467KI7Zi4KeuhnCBjbGFzc2lmaWNhdGlvbuydhCDsl7DsirXtlbTrs7TsnpAuICANCg0KIyDrjbDsnbTthLAg7IK07Y6067O06riwIA0KYGBge3IgaW5jbHVkZT1GQUxTRSwgZWNobz1GQUxTRX0NCmtuaXRyOjpvcHRzX2NodW5rJHNldChjb21tZW50ID0gIiIgLCBwcm9tcHQgPSBUUlVFLCBvdXQud2lkdGggPSA1MDAsIGZpZy5oZWlnaHQgPSAxMCwgZmlnLndpZHRoID0gMTApDQpsaWJyYXJ5KGtuaXRyKQ0KU3lzLnNldGxvY2FsZSgiTENfQUxMIiwgIktvcmVhbiIpDQpzZXR3ZCgiRTovRHJvcGJveC8wMC4yMDE4LzAxLjIwMThfMV9zZW1lc3Rlci8wMS5EYXRhTWluaW5nLzA0LkhXL0hXNCIpDQpgYGAgDQoNCi0g7J2067KI7JeQIOu2hOyEne2VoCDrgrTsmqnsnYAgTU5JU1Trnbzqs6Ag67aA66W064qUIOycoOuqhe2VnCDsmrDtjrjrsojtmLgg642w7J207YSw7J2064ukLiANCi0g7Iir7J6Q6rCAIOygge2ejCDsiJjrp47snYAg642w7J207YSw66W8IGNsYXNzaWZpY2F0aW9u7Iuc7Lyc7IScIOq4sOqzhOqwgCDsiqTsiqTroZwg7Iir7J6Q66W8IOydveydhCDsiJgg7J6I64+E66GdIO2VmOuKlCDqsoPsnbTri6QuIA0KLSDsi6TsoJwg7Jqw7LK06rWt7JeQ7IScIOyasO2OuOuyiO2YuOulvCDsnbjsi53tlbTshJwg6riw6rOE6rCAIOyekOuPmeycvOuhnCDsmrDtjrjrrLzsnYQg67aE66WY7ZWY64+E66GdIOydtOyaqe2VmOqzoCDsnojri6QuIA0KDQoNCmBgYHtyIGVjaG89RkFMU0V9DQptbmlzdC50cmFpbi5sYXJnZSA8LSByZWFkLmNzdigiTU5JU1RfdHJhaW4uY3N2IikNCm1uaXN0LnRlc3QubGFyZ2UgPC0gcmVhZC5jc3YoIk1OSVNUX3Rlc3QuY3N2IikNCg0KbW5pc3QudHJhaW4gPC0gbW5pc3QudHJhaW4ubGFyZ2UNCm1uaXN0LnRlc3Q8LSBtbmlzdC50ZXN0LmxhcmdlDQoNCmBgYA0KDQojIyMjIOuzgOyImOqwnOyImCAmIOq0gOy4oey5mCDqsJzsiJgNCmBgYHtyfQ0KZGltKG1uaXN0LnRyYWluKSA7IGRpbShtbmlzdC50ZXN0KSA7cmFuZ2UobW5pc3QudHJhaW5bLC0xXSkNCg0KYGBgDQotIOqwgeqwgSA3ODXqsJzsnZgg67OA7IiY66GcIOq1rOyEseuQmOyXiOuLpC4gDQotIOqwgSDrs4DsiJjripQg7J2066+47KeA7J2YIO2UveyFgOydhCDsnZjrr7jtlZjrqbAsIOuzgOyImOqwkuydgCDtlL3shYDsnZgg66qF64+E66W8IOuCmO2DgOuCuOuLpC4gDQotIO2UveyFgOydmCDrqoXrj4TripQgMH4xIOyCrOydtOydmCDqsJLsnYQg6rCA7KeE64ukLiANCg0KPGJyLz4NCi0gdHJhaW5pbmcgc2V07J2AIDbrp4zqsbTsnZgg642w7J207YSw66GcIOydtOujqOyWtOyguOyeiOqzoCwNCi0gdGVzdCBzZXTsnYAg66eM6rG07J2YIOuNsOydtO2EsOuhnCDsnbTro6jslrTsoLjsnojri6QuIA0KDQoNCg0KIyMjIyDqsrDsuKHqsJIg7ZmV7J24DQpgYGB7cn0NCnN1bShpcy5uYShtbmlzdC50cmFpbikpIDtzdW0oaXMubmEobW5pc3QudGVzdCkpDQpgYGANCi0g6rKw7Lih6rCS7J2AIO2VmOuCmOuPhCDsl4bri6QuIOq3uOufvCDquLDrtoTsoovqsowg67aE7ISd7J2EIOyLnOyeke2VtOuztOuPhOuhnSDtlZjsnpAhDQoNCg0KDQoNCg0KIyBLbm4gKHdpdGggTE9PQ1YpDQotIEtubiBjbGFzc2lmaWNhdGlvbuydtOuegCwg7ZW064u5IOuNsOydtO2EsOyZgCDqsbDrpqzqsIAg6rCA7J6lIOqwgOq5jOyatCDrjbDsnbTthLDrk6TsnYQg7LC46rOg7ZW07IScIOu2hOulmOu2hOyEne2VmOuKlCDrsKnrspXsnbTri6QuIA0KLSDsmIjrprzsnbTsnZgg7ISx7KCB7J2EIOyVjOqzoCDsi7bri6TrqbQsIOyYiOumvOydtOydmCDsuZztlZwg7Lmc6rWs65Ok7J2YIOyEseyggeydhCDssLjqs6DtlbTshJwsIOyYiOumvOydtOydmCDshLHsoIHsnYQg7Jyg7LaU7ZW067O064qUIOqyg+qzvCDqsJnsnYAg7JWM6rOg66as7KaY7J2064ukLiAtIEtubuydhCBMT09DVuulvCDsnbTsmqntlbTshJwg67aE7ISd7ZW067O07JWY64ukLiANCg0KYGBge3IsIGVjaG89RkFMU0V9DQpsaWJyYXJ5KGNsYXNzKQ0Kc2V0LnNlZWQoMTIzNCkNCmVycm9yPC1saXN0KCkNCnByZWRpY3Qua25uIDwtIGxpc3QoKQ0KDQpmb3IgKGkgaW4gMToxMCl7DQogIHByZWRpY3Qua25uW1tpXV0gPC0ga25uLmN2KG1uaXN0LnRyYWluWywtMV0sDQogICAgICAgICAgICAgICAgICAgbW5pc3QudHJhaW5bLDFdLGs9MSkNCn0NCmBgYA0KDQoNCmBgYHtyfQ0KZXJyb3IgPC0gbGlzdCgpDQpmb3IgKCBpIGluIDE6MTApew0KZXJyb3JbW2ldXTwtbWVhbihwcmVkaWN0LmtubltbaV1dIT1tbmlzdC50ZXN0WywxXSkNCn0NCg0KZXJyb3IubGlzdCA8LSB1bmxpc3QoZXJyb3IpDQplcnJvci5saXN0DQpgYGANCg0KLSBrPTEsMixgYGAsMTDsnZgg6rKw6rO86rCAIOuqqOuRkCDrj5nsnbztlZjri6QuIGVycm9yIHJhdGUoMC4wMzA5KeqwgCDrqqjrkZAg6rCZ64ukLiANCmBgYHtyfQ0KbWVhbihwcmVkaWN0LmtubltbMV1dPT0gYXMuZmFjdG9yKG1uaXN0LnRlc3RbLDFdKSkgI2FjY3VyYWN5IHJhdGUNCg0KYGBgDQotIGtubuydmCBhY2N1cmFjeSByYXRl64qUIDAuOTY5MeuhnCDrgpjsmZTri6QuIA0KDQpgYGB7cn0NCg0KdGFibGUocHJlZGljdC5rbm5bWzFdXSwgYXMuZmFjdG9yKG1uaXN0LnRlc3RbLDFdKSkNCg0KYGBgDQoNCi0gaz0x7J24IOqyveyasOuhnCDrhpPqs6Ag6rWs7ZWcIGNvbmZ1c3Rpb24gbWF0cml47J2064ukLiANCi0g7Yq567OE7ZWcIOq3nOy5meyEseydtOuCmCDqsr3tlqXsnYAg67O07J207KeAIOyViuuKlOuLpC4gDQotIOyLpOygnOqwkuydgCA07J24642wLCA566GcIG1pc2NsYXNzaWZ57ZWcIOqyveyasOqwgCAyMuqxtOycvOuhnCDqsIDsnqUg66eO6rOgLCANCi0g65GQ67KI7Ke466GcIOunjuydgCBtaXNjbGFzc2lmaWNhdGlvbuydgCDsi6TsoJzqsJLsnbQgM+yduOqyg+ydhCA166GcIG1pc2NsYXNzaWZ57ZWcIOqyveyasOydtOuLpC4gDQoNCj4g656c642k7Y+s66CI7Iqk7Yq466GcIOuEmOyWtOqwgOuztOyekC4gDQoNCioqKg0KDQoNCg0KIyByYW5kb21mb3Jlc3QNCmBgYHtyfQ0KbGlicmFyeShyYW5kb21Gb3Jlc3QpDQpzZXQuc2VlZCgxKQ0KcmYuaDwtcmFuZG9tRm9yZXN0KGFzLmZhY3Rvcih5KX4uLGRhdGE9bW5pc3QudHJhaW4sbXRyeT0yOCxpbXBvcnRhbmNlPVQpDQpyZi5oDQoNCg0KYGBgDQotIOuenOuNpO2PrOugiOyKpO2KuCDqsrDqs7zsnbTri6QuIA0KLSBzcGxpdOydgCAkXHNxcnQgNzg1ID0gMjgk66GcIOuGk+qzoCDtkoDsl4jri6QuIA0KLSBPT0IgZXJyb3IgcmF0ZeuKlCDslb0gMi45NiXsnbTri6QuIOqysOqzvOqwgCDsoJXrp5Ag7KKL64ukLiDsmKTrpZjqsIAg7J2066CH6rKM64KYIOyggeuLpOuLiC4uLiENCi0g6rCBIOyIq+yekOydmCBjbGFzcyBlcnJvciByYXRl66W8IOyCtO2OtOuztOuptCAqKjMqKiwgKio4KiosICoqOSoq7J2YIGVycm9yIHJhdGXqsIAg6rCB6rCBIDAuMDQyLCAwLjA0NCwgMC4wNDfroZwg67mE6rWQ7KCBIOuGkuqyjCDrgpjsmZTri6QuDQotIDMsOCw5IC0+IOydtCDshLgg7Iir7J6QIOuqqOyWkeydtCDruYTsirftlbTshJwg6re465+wIOqygyDqsJnri6QuIA0KLSDsi6TsoJzroZwgY29uZnVzaW9uIG1hdHJpeOulvCDthrXtlbQgbWlzY2xhc3NpZmljYXRpb27tlZwg6rKD7J2EIOuztOuptCAgM+qzvCA4LDnrpbwg7ISc66GcIO2YvOuPme2VtOyEnCBjbGFzc2lmaWNhdGlvbiDtlZwg6rK97Jqw6rCAIOunjuuLpOuKlCDqsoPsnYQg67O8IOyImCDsnojri6QuIA0KLSBrbm7sl5DshJzripQg7Jik67aE66WY7JeQ64yA7ZWcIOyWtOuWpCDtirnsoJXtlZwg6rK97Zal7J20IOyViCDrs7TsmIDripTrjbAsIA0KDQo+IOyYpOulmOulvCDspITsnbTqs6Ag7Iu264uk66m0LCAzLDgsOeulvCDsnpgg6rWs67aE7ZWgIOyImCDsnojrj4TroZ0g7ZWZ7Iq1IOyLnO2CpOuKlCDqsoPsnbQg7KSR7JqU7ZWY6rKg64ukLiANCg0KDQpgYGB7ciBpbmNsdWRlPUZBTFNFfQ0KeWhhdC5yZjwtcHJlZGljdChyZi5oLG5ld2RhdGE9bW5pc3QudGVzdCkNCg0KYGBgDQoNCmBgYHtyfQ0KbWVhbih5aGF0LnJmIT1tbmlzdC50ZXN0JHkpOyBtZWFuKHloYXQucmY9PW1uaXN0LnRlc3QkeSkNCmBgYA0KLSByYW5kb21mb3Jlc3TroZwg67aE7ISd7ZaI7J2EIOuVjOydmCBlcnJvciByYXRl64qUIDAuMDI4OOydtOuLpC4NCi0gYWNjdXJhY3kgcmF0ZeuKlCAwLjk3MTLsnbTri6QuICANCg0KPGJyLz4NCg0KIyMjIyB2YXJpYW5jZSBpbXBvcnRhbmNlIHBsb3QNCmBgYHtyLCBmaWcud2lkdGg9MTUsIGZpZy5oZWlnaHQ9MTV9DQojIGltcG9ydGFuY2UocmYuaCkNCnZhckltcFBsb3QocmYuaCkNCmBgYA0KDQoNCmBgYHtyIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9DQp0bXAgPC0gaW1wb3J0YW5jZShyZi5oKQ0KdG1wIDwtIGFzLmRhdGEuZnJhbWUodG1wKQ0KDQojIG1lYW4gZGVjcmVhc2UgYWNjdXJhY3nrpbwg7J207Jqp7ZW0IOqwgOyepSDrp47snYAg7JiB7Zal7J2EIOyjvOuKlCDrs4DsiJgg7IOB7JyEIDEw6rCc66W8IOqzqOuekOuLpC4gDQpoZWFkKG9yZGVyKHRtcCRNZWFuRGVjcmVhc2VBY2N1cmFjeSwgZGVjcmVhc2luZz1UKSwgbj0xMCkNCmBgYA0KDQpgYGB7cn0NCiMgbWVhbiBkZWNyZWFzZSBnaW5p66W8IO2Gte2VtCDsgrTtjrTrs7gg7IOB7JyEIDEw6rCcIOuzgOyImEBAQA0KaGVhZChvcmRlcih0bXAkTWVhbkRlY3JlYXNlR2luaSwgZGVjcmVhc2luZz1UKSwgbj0xMCkNCmBgYA0KLSDslrTrlqQg67OA7IiY6rCAIOykkeyalO2VnCDsmIHtlqXsnYQg66+47LmY64qU7KeAIOyCtO2OtOuztOyVmOuKlOuNsCwg7ZiEIOuNsOydtO2EsOyXkOyEnOuKlCDtgbAg7J2Y66+46rCAIOyXhuuKlCDqsoMg6rCZ64ukLiANCi0g7J2066+47KeAIOuNsOydtO2EsOyXkOyEnOuKlCDrs4DsiJjqsIAg7KSR7JqU7ZWcIOydmOuvuOulvCDqsIDsp4Dsp4Ag7JWK6riwIOuVjOusuOydtOuLpC4uLi4uIA0KDQo+IOuniOyngOunieycvOuhnCBib29zdGluZ+ydhCDtlbTrs7TsnpAuIA0KDQoqKioNCg0KIyBCb29zdGluZw0KYGBge3IgaW5jbHVkZT1GQUxTRX0NCmxpYnJhcnkobWFib29zdCkNCnJlc3VsdC5ib29zdGluZyA8LSBtYWJvb3N0KG1uaXN0LnRyYWluWywtMV0sIA0KICAgICAgICAgICAgICAgICAgYXMuZmFjdG9yKG1uaXN0LnRyYWluJHkpKQ0KDQpgYGANCg0KYGBge3J9DQpyZXN1bHQuYm9vc3RpbmcNCm1lYW4ocmVzdWx0LmJvb3N0aW5nJGZpdCA9PSBtbmlzdC50cmFpbiR5KSAjYWNjdXJhY3kNCg0KYGBgDQotIGJvb3N0aW5nIOqysOqzvOqwgCDsg53qsIHrs7Tri6Qg7KKL6rKMIOuCmOyYpOyngCDslYrslZjri6QuIA0KLSBhY2NhcmFjeSByYXRl64qUIDAuODg0MOydtOqzoCwgZXJyb3IgcmF0ZeuKlCAwLjExNjAuDQotIE9PQiBlcnJvcuuKlCAwLjEyN+uhnCDrgpjsmZTri6QodGVzdCBlcnJvcuydmCDstpTsoJXqsJLsnbTrnbwg7IOd6rCB7ZWY66m0IOuQnOuLpCkNCi0gYm9vc3RpbmfsnYAg7JuQ656YIGJpbmFyeSBvdXRwdXTsl5Ag7LWc7KCB7ZmU65Cc6rG0642wLCDsmrDrpqwg642w7J207YSw64qUIG11bHRpY2xhc3Mgb3V0cHV07J207Ja07IScIOuqqO2Yleygge2VqeuPhOqwgCDrlqjslrTsp4DripQg6rKDIOqwmeuLpC4gDQoNCioqKg0KDQoNCg0KIyBTdW1tYXJ5DQpgYGB7ciBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFLCBlY2hvPUZBTFNFfQ0Kb3B0aW9ucyhrbml0ci50YWJsZS5mb3JtYXQ9Imh0bWwiKQ0Kb3B0aW9ucyhrYWJsZUV4dHJhLmF1dG9fZm9ybWF0PUYpDQoNCmxpYnJhcnkoa2FibGVFeHRyYSkNCm5hbWVzIDwtIGMoIktubiIsIlJGIiwiQm9vc3RpbmciKQ0KQWNjIDwtIGMoMC45NjkxLCAwLjk3LDAuODgpDQplcnJvciA8LSBjKDAuMDMxLCAwLjAyOSwgMC4xMTYpDQpFVCA8LSBjKCIxOWgiLCI2aCIsIjJoIikNClJlbWFya3MgPC0gYygi6rOE7IKw7Iuc6rCEIOuEiOustCDsmKTrnpgg6rG466a8IiwNCiAgICAgICAgICAgICAiYm9vc3Rpbmfrs7Tri6Qg7Ken7J2AIOqzhOyLoOyLnOqwhOyXkCDruYTsirftlZwg7KCV7ZmV64+EIiwNCiAgICAgICAgICAgICAi6rOE7IKw7Iuc6rCEIOunpOyasCDsp6fsnLzrgpgsIOygle2ZleuPhOqwgCDrhIjrrLQg64Ku7JWE7IScIOyVhOyJrOybgCAiKQ0KbmFtZXMoQWNjKSA8LSBuYW1lcw0KbmFtZXMoZXJyb3IpIDwtIG5hbWVzDQpuYW1lcyhFVCkgPC0gbmFtZXMNCm5hbWVzKFJlbWFya3MpIDwtIG5hbWVzDQpkZiA8LSBhcy5kYXRhLmZyYW1lKGNiaW5kKEFjYyxlcnJvciwgRVQsIFJlbWFya3MpKQ0KDQoNCmthYmxlKGRmLCByb3cubmFtZXMgPSBULCBmb3JtYXQ9Imh0bWwiKSU+JSANCiAga2FibGVfc3R5bGluZyhib290c3RyYXBfb3B0aW9ucyA9IGMoInN0cmlwZWQiLCJob3ZlciIpLGZ1bGxfd2lkdGg9RikgJT4lIA0KICBjb2x1bW5fc3BlYyg0LCB3aWR0aCA9ICIzZW0iICkNCmBgYA0KDQotIGtubiwgcmFuZG9tZm9yZXN0LCBib29zdGluZyDsnbTsg4EgM+qwnCDrsKnrspXsnYQg7KKF7ZWp7ZW067O07JWY64ukLiANCi0g64KY652866m0IOyhsOq4iCDsmKTrnpgg6rG466as642U652864+EIHJhbmRvbWZvcmVzdOuhnCDrtoTshJ3tlaAg6rKDIOqwmeuLpC4gDQoNCj4g64GdISEh