Tên: Mai Huy

MSSV: 43.01.104.065

Số thứ tự: 08

1) Bagging

# Cài thư viện Random Forest
install.packages("randomForest")
# Load thư viện random forest
library(randomForest)
randomForest 4.6-14
Type rfNews() to see new features/changes/bug fixes.
# Load thư viện Mass
library(MASS)
# Load thư viện tree
library(tree)
# set.seed dùng để tái tạo những vector random giống nhau theo tương ứng với giá trị được đưa vào hàm seed
set.seed (1)
# CHia random tập train với số lượng quan sát được chia đôi trong dữ liệu Boston
train = sample(1:nrow(Boston), nrow(Boston)/2)
# Tạo mô hình randomforest để dự đoan giá trị medv là biến đầu ra và lấy tất cả các biến còn lại làm biến đầu vào trong tập train đã chia của dữ liệu Boston
bag.boston = randomForest(medv~.,data=Boston,subset =
train, mtry = 13,importance =TRUE)
# Thông tin mô hình vừa xây dựng
bag.boston

Call:
 randomForest(formula = medv ~ ., data = Boston, mtry = 13, importance = TRUE,      subset = train) 
               Type of random forest: regression
                     Number of trees: 500
No. of variables tried at each split: 13

          Mean of squared residuals: 11.33119
                    % Var explained: 85.26
# Đưa ra dự đoán trên tập test nằm ngoài tập train, biến yhat.bag trả về các giá trị dự đoán trên tập test
yhat.bag = predict(bag.boston,newdata=Boston[-train,])
# Trích xuất kết quả giá trị output medv thật của tập test
boston.test = Boston[-train , "medv"]
# Hiển thị biểu đồ phân tán với cột x là giá trị được dự đoán và cột y là giá trị thật của tập test
plot(yhat.bag, boston.test)
# Gốc toạ độ được chọn 0 ở trục hoành, 1 ở trục tung
abline(0,1)

# Tính Mean Squared Error (MSE) giữa giá trị dự đoán và giá trị thật
mean((yhat.bag-boston.test)^2)
[1] 23.4579

MSE của tập test là 23.4579

# Tạo mô hình randomforest để dự đoan giá trị medv là biến đầu ra và lấy tất cả các biến còn lại làm biến đầu vào trong tập train đã chia của dữ liệu Boston
bag.boston=randomForest(medv~.,data=Boston,subset=train, mtry=13,ntree=25)
# Đưa ra dự đoán trên tập test nằm ngoài tập train, biến yhat.bag trả về các giá trị dự đoán trên tập test
yhat.bag = predict(bag.boston,newdata=Boston[-train,])
# Tính Mean Squared Error (MSE) giữa giá trị dự đoán và giá trị thật
mean((yhat.bag-boston.test)^2)
[1] 22.99145

MSE của tập test là 22.99145

# set.seed dùng để tái tạo những vector random giống nhau theo tương ứng với giá trị được đưa vào hàm seed
set.seed(1)
# Tạo mô hình randomforest để dự đoan giá trị medv là biến đầu ra và lấy tất cả các biến còn lại làm biến đầu vào trong tập train đã chia của dữ liệu Boston
rf.boston=randomForest(medv~.,data=Boston,subset=train,mtry=6,importance=TRUE)
# Đưa ra dự đoán trên tập test nằm ngoài tập train, biến yhat.bag trả về các giá trị dự đoán trên tập test
yhat.rf = predict(rf.boston,newdata=Boston[-train,])
# Tính Mean Squared Error (MSE) giữa giá trị dự đoán và giá trị thật
mean((yhat.rf-boston.test)^2)
[1] 19.62021

MSE của tập test là 19.62021

# Hiển thị mức độ quan trọng của các biến
importance(rf.boston)
          %IncMSE IncNodePurity
crim    16.697017    1076.08786
zn       3.625784      88.35342
indus    4.968621     609.53356
chas     1.061432      52.21793
nox     13.518179     709.87339
rm      32.343305    7857.65451
age     13.272498     612.21424
dis      9.032477     714.94674
rad      2.878434      95.80598
tax      9.118801     364.92479
ptratio  8.467062     823.93341
black    7.579482     275.62272
lstat   27.129817    6027.63740

%IncMSE là mức độ quan trọng của biến dựa trên sự giảm trung bình trong độ chính xác dự đoán được đưa ra từ lớp out of bag

IncNodePurity là tổng các giá trị giảm trong các node được chia, của tất cả các cây

# Plot biểu đồ thể hiện độ quan trọng của các biến
varImpPlot(rf.boston)

2) Booting

# Load thư viện gbm
library(gbm)
Loaded gbm 2.1.5
# set.seed dùng để tái tạo những vector random giống nhau theo tương ứng với giá trị được đưa vào hàm seed
set.seed(1)
# Tạo mô hình hồi quy ổng quan boosting với biến đầu ra là medv, biến đầu vào là tất cả các biến còn lại, với số lượng cây là 5000, độ sâu tối đa của cây là 4, mô hình theo phân phối gaussian
boost.boston=gbm(medv~.,data=Boston[train,],distribution="gaussian",n.trees=5000,interaction.depth=4)

Hàm summary() cho chúng ta một bảng và 1 biểu đồ cho biết mức độ ảnh hưởng của các biến, ta thấy biến rm có mức độ ảnh hưởng cao nhất là 43.9919329

#Biểu đồ phân tán của các biến  dữ liệu với các dữ liệu cột được chia thành cửa sổ 1x2 bằng cách sử dụng hàm mfrow=c(1,2) 
par(mfrow=c(1,2))
# Biểu đồ biểu diễn mức độ ảnh hưởng của biến rm
plot(boost.boston,i="rm")

# Biểu đồ biểu diễn mức độ ảnh hưởng của biến lstat
plot(boost.boston,i="lstat")

# Tiến hành dự đoán tập test nằm ngoài tập train với số lượng cây = 5000
yhat.boost=predict(boost.boston,newdata=Boston[-train,],n.trees=5000)
# Tính Mean Squared Error (MSE) giữa giá trị dự đoán và giá trị thật
mean((yhat.boost-boston.test)^2)
[1] 18.84709

MSE của tập test là 18.84709

# Tạo mô hình hồi quy ổng quan boosting với biến đầu ra là medv, biến đầu vào là tất cả các biến còn lại
boost.boston=gbm(medv~.,data=Boston[train,],distribution="gaussian",n.trees=5000,interaction.depth=4,shrinkage=0.2,verbose=F)
# Tiến hành dự đoán tập test nằm ngoài tập train với số lượng cây = 5000
yhat.boost=predict(boost.boston,newdata=Boston[-train,],n.trees=5000)
# Tính Mean Squared Error (MSE) giữa giá trị dự đoán và giá trị thật
mean((yhat.boost-boston.test)^2)
[1] 18.33455

MSE của tập test là 18.33455

LS0tDQp0aXRsZTogIkJhZ2dpbmctUmFuZG9tIEZvcmVzdC1Cb29zdGluZy1UdeG6p24gMTAiDQpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sNCi0tLQ0KDQojIyMgVMOqbjogTWFpIEh1eQ0KIyMjIE1TU1Y6IDQzLjAxLjEwNC4wNjUNCiMjIyBT4buRIHRo4bupIHThu7E6IDA4DQoNCg0KIyMgMSkgQmFnZ2luZw0KDQpgYGB7cn0NCiMgQ8OgaSB0aMawIHZp4buHbiBSYW5kb20gRm9yZXN0DQppbnN0YWxsLnBhY2thZ2VzKCJyYW5kb21Gb3Jlc3QiKQ0KYGBgDQoNCmBgYHtyfQ0KIyBMb2FkIHRoxrAgdmnhu4duIHJhbmRvbSBmb3Jlc3QNCmxpYnJhcnkocmFuZG9tRm9yZXN0KQ0KIyBMb2FkIHRoxrAgdmnhu4duIE1hc3MNCmxpYnJhcnkoTUFTUykNCiMgTG9hZCB0aMawIHZp4buHbiB0cmVlDQpsaWJyYXJ5KHRyZWUpDQpgYGANCg0KDQpgYGB7cn0NCiMgc2V0LnNlZWQgZMO5bmcgxJHhu4MgdMOhaSB04bqhbyBuaOG7r25nIHZlY3RvciByYW5kb20gZ2nhu5FuZyBuaGF1IHRoZW8gdMawxqFuZyDhu6luZyB24bubaSBnacOhIHRy4buLIMSRxrDhu6NjIMSRxrBhIHbDoG8gaMOgbSBzZWVkDQpzZXQuc2VlZCAoMSkNCiMgQ0hpYSByYW5kb20gdOG6rXAgdHJhaW4gduG7m2kgc+G7kSBsxrDhu6NuZyBxdWFuIHPDoXQgxJHGsOG7o2MgY2hpYSDEkcO0aSB0cm9uZyBk4buvIGxp4buHdSBCb3N0b24NCnRyYWluID0gc2FtcGxlKDE6bnJvdyhCb3N0b24pLCBucm93KEJvc3RvbikvMikNCiMgVOG6oW8gbcO0IGjDrG5oIHJhbmRvbWZvcmVzdCDEkeG7gyBk4buxIMSRb2FuIGdpw6EgdHLhu4sgbWVkdiBsw6AgYmnhur9uIMSR4bqndSByYSB2w6AgbOG6pXkgdOG6pXQgY+G6oyBjw6FjIGJp4bq/biBjw7JuIGzhuqFpIGzDoG0gYmnhur9uIMSR4bqndSB2w6BvIHRyb25nIHThuq1wIHRyYWluIMSRw6MgY2hpYSBj4bunYSBk4buvIGxp4buHdSBCb3N0b24NCmJhZy5ib3N0b24gPSByYW5kb21Gb3Jlc3QobWVkdn4uLGRhdGE9Qm9zdG9uLHN1YnNldCA9DQp0cmFpbiwgbXRyeSA9IDEzLGltcG9ydGFuY2UgPVRSVUUpDQpgYGANCg0KLSBtdHJ5ID0xMzogY8OzIDEzIHnhur91IHThu5EgxJHhuqd1IHbDoG8gxJHGsOG7o2Mgc+G7rSBk4bulbmcgY2hvIG3hu5dpIGzDumMgcGjDom4gY2hpYSBjw6J5IA0KLSBpbXBvcnRhbmNlID1UUlVFOiBYdeG6pXQgcmEgxJHhu5kgcXVhbiB0cuG7jW5nIGPDoWMgYmnhur9uDQoNCmBgYHtyfQ0KIyBUaMO0bmcgdGluIG3DtCBow6xuaCB24burYSB4w6J5IGThu7FuZw0KYmFnLmJvc3Rvbg0KYGBgDQoNCi0gTG/huqFpIG3DtCBow6xuaCA6IFJlZ3Jlc3Npb24gKMaw4bubYyB0w61uaCBnacOhIHRy4buLKQ0KLSBT4buRIGzGsOG7o25nIGJp4bq/biAgbeG7l2kgbOG6p24gcGjDom4gY2hpYSBuaMOhbmggOiAxMw0KLSBUcnVuZyBiw6xuaCBiw6xuaCBwaMawxqFuZyByZXNpZHVhbCBj4bunYSB04bqtcCB0cmFpbiBsw6AgMTEuMzMxMTkNCi0gVOG7iSBs4buHIGThu7EgxJFvw6FuIGNow61uaCB4w6FjIGPhu6dhIG91dC1vZi1iYWcgY2hvIHThuq1wIHRyYWluIGzDoCA4NS4yNg0KDQpgYGB7cn0NCiMgxJDGsGEgcmEgZOG7sSDEkW/DoW4gdHLDqm4gdOG6rXAgdGVzdCBu4bqxbSBuZ2/DoGkgdOG6rXAgdHJhaW4sIGJp4bq/biB5aGF0LmJhZyB0cuG6oyB24buBIGPDoWMgZ2nDoSB0cuG7iyBk4buxIMSRb8OhbiB0csOqbiB04bqtcCB0ZXN0DQp5aGF0LmJhZyA9IHByZWRpY3QoYmFnLmJvc3RvbixuZXdkYXRhPUJvc3RvblstdHJhaW4sXSkNCmBgYA0KDQpgYGB7cn0NCiMgVHLDrWNoIHh14bqldCBr4bq/dCBxdeG6oyBnacOhIHRy4buLIG91dHB1dCBtZWR2IHRo4bqtdCBj4bunYSB04bqtcCB0ZXN0DQpib3N0b24udGVzdCA9IEJvc3RvblstdHJhaW4gLCAibWVkdiJdDQpgYGANCg0KYGBge3J9DQojIEhp4buDbiB0aOG7iyBiaeG7g3UgxJHhu5MgcGjDom4gdMOhbiB24bubaSBj4buZdCB4IGzDoCBnacOhIHRy4buLIMSRxrDhu6NjIGThu7EgxJFvw6FuIHbDoCBj4buZdCB5IGzDoCBnacOhIHRy4buLIHRo4bqtdCBj4bunYSB04bqtcCB0ZXN0DQpwbG90KHloYXQuYmFnLCBib3N0b24udGVzdCkNCiMgR+G7kWMgdG/huqEgxJHhu5kgxJHGsOG7o2MgY2jhu41uIDAg4bufIHRy4bulYyBob8OgbmgsIDEg4bufIHRy4bulYyB0dW5nDQphYmxpbmUoMCwxKQ0KYGBgDQoNCmBgYHtyfQ0KIyBUw61uaCBNZWFuIFNxdWFyZWQgRXJyb3IgKE1TRSkgZ2nhu69hIGdpw6EgdHLhu4sgZOG7sSDEkW/DoW4gdsOgIGdpw6EgdHLhu4sgdGjhuq10DQptZWFuKCh5aGF0LmJhZy1ib3N0b24udGVzdCleMikNCmBgYA0KDQoNCk1TRSBj4bunYSB04bqtcCB0ZXN0IGzDoCAyMy40NTc5DQoNCmBgYHtyfQ0KIyBU4bqhbyBtw7QgaMOsbmggcmFuZG9tZm9yZXN0IMSR4buDIGThu7EgxJFvYW4gZ2nDoSB0cuG7iyBtZWR2IGzDoCBiaeG6v24gxJHhuqd1IHJhIHbDoCBs4bqleSB04bqldCBj4bqjIGPDoWMgYmnhur9uIGPDsm4gbOG6oWkgbMOgbSBiaeG6v24gxJHhuqd1IHbDoG8gdHJvbmcgdOG6rXAgdHJhaW4gxJHDoyBjaGlhIGPhu6dhIGThu68gbGnhu4d1IEJvc3Rvbg0KYmFnLmJvc3Rvbj1yYW5kb21Gb3Jlc3QobWVkdn4uLGRhdGE9Qm9zdG9uLHN1YnNldD10cmFpbiwgbXRyeT0xMyxudHJlZT0yNSkNCmBgYA0KDQotIG10cnkgPTEzOiBjw7MgMTMgeeG6v3UgdOG7kSDEkeG6p3UgdsOgbyDEkcaw4bujYyBz4butIGThu6VuZyBjaG8gbeG7l2kgbMO6YyBwaMOibiBjaGlhIGPDonkgDQotIG50cmVlID0gMjU6IHPhu5EgbMaw4bujbmcgY8OieSBsw6AgMjUNCg0KYGBge3J9DQojIMSQxrBhIHJhIGThu7EgxJFvw6FuIHRyw6puIHThuq1wIHRlc3QgbuG6sW0gbmdvw6BpIHThuq1wIHRyYWluLCBiaeG6v24geWhhdC5iYWcgdHLhuqMgduG7gSBjw6FjIGdpw6EgdHLhu4sgZOG7sSDEkW/DoW4gdHLDqm4gdOG6rXAgdGVzdA0KeWhhdC5iYWcgPSBwcmVkaWN0KGJhZy5ib3N0b24sbmV3ZGF0YT1Cb3N0b25bLXRyYWluLF0pDQojIFTDrW5oIE1lYW4gU3F1YXJlZCBFcnJvciAoTVNFKSBnaeG7r2EgZ2nDoSB0cuG7iyBk4buxIMSRb8OhbiB2w6AgZ2nDoSB0cuG7iyB0aOG6rXQNCm1lYW4oKHloYXQuYmFnLWJvc3Rvbi50ZXN0KV4yKQ0KYGBgDQoNCk1TRSBj4bunYSB04bqtcCB0ZXN0IGzDoCAyMi45OTE0NQ0KDQpgYGB7cn0NCiMgc2V0LnNlZWQgZMO5bmcgxJHhu4MgdMOhaSB04bqhbyBuaOG7r25nIHZlY3RvciByYW5kb20gZ2nhu5FuZyBuaGF1IHRoZW8gdMawxqFuZyDhu6luZyB24bubaSBnacOhIHRy4buLIMSRxrDhu6NjIMSRxrBhIHbDoG8gaMOgbSBzZWVkDQpzZXQuc2VlZCgxKQ0KIyBU4bqhbyBtw7QgaMOsbmggcmFuZG9tZm9yZXN0IMSR4buDIGThu7EgxJFvYW4gZ2nDoSB0cuG7iyBtZWR2IGzDoCBiaeG6v24gxJHhuqd1IHJhIHbDoCBs4bqleSB04bqldCBj4bqjIGPDoWMgYmnhur9uIGPDsm4gbOG6oWkgbMOgbSBiaeG6v24gxJHhuqd1IHbDoG8gdHJvbmcgdOG6rXAgdHJhaW4gxJHDoyBjaGlhIGPhu6dhIGThu68gbGnhu4d1IEJvc3Rvbg0KcmYuYm9zdG9uPXJhbmRvbUZvcmVzdChtZWR2fi4sZGF0YT1Cb3N0b24sc3Vic2V0PXRyYWluLG10cnk9NixpbXBvcnRhbmNlPVRSVUUpDQoNCmBgYA0KDQotIG10cnkgPTYgOiBjw7MgNiB54bq/dSB04buRIMSR4bqndSB2w6BvIMSRxrDhu6NjIHPhu60gZOG7pW5nIGNobyBt4buXaSBsw7pjIHBow6JuIGNoaWEgY8OieSANCi0gaW1wb3J0YW5jZSA9VFJVRTogWHXhuqV0IHJhIMSR4buZIHF1YW4gdHLhu41uZyBjw6FjIGJp4bq/bg0KDQoNCmBgYHtyfQ0KIyDEkMawYSByYSBk4buxIMSRb8OhbiB0csOqbiB04bqtcCB0ZXN0IG7hurFtIG5nb8OgaSB04bqtcCB0cmFpbiwgYmnhur9uIHloYXQuYmFnIHRy4bqjIHbhu4EgY8OhYyBnacOhIHRy4buLIGThu7EgxJFvw6FuIHRyw6puIHThuq1wIHRlc3QNCnloYXQucmYgPSBwcmVkaWN0KHJmLmJvc3RvbixuZXdkYXRhPUJvc3RvblstdHJhaW4sXSkNCiMgVMOtbmggTWVhbiBTcXVhcmVkIEVycm9yIChNU0UpIGdp4buvYSBnacOhIHRy4buLIGThu7EgxJFvw6FuIHbDoCBnacOhIHRy4buLIHRo4bqtdA0KbWVhbigoeWhhdC5yZi1ib3N0b24udGVzdCleMikNCmBgYA0KDQpNU0UgY+G7p2EgdOG6rXAgdGVzdCBsw6AgMTkuNjIwMjENCg0KYGBge3J9DQojIEhp4buDbiB0aOG7iyBt4bupYyDEkeG7mSBxdWFuIHRy4buNbmcgY+G7p2EgY8OhYyBiaeG6v24NCmltcG9ydGFuY2UocmYuYm9zdG9uKQ0KDQpgYGANCg0KJUluY01TRSBsw6AgbeG7qWMgxJHhu5kgcXVhbiB0cuG7jW5nIGPhu6dhIGJp4bq/biBk4buxYSB0csOqbiBz4buxIGdp4bqjbSB0cnVuZyBiw6xuaCB0cm9uZyDEkeG7mSBjaMOtbmggeMOhYyBk4buxIMSRb8OhbiDEkcaw4bujYyDEkcawYSByYSB04burIGzhu5twIG91dCBvZiBiYWcNCg0KSW5jTm9kZVB1cml0eSBsw6AgdOG7lW5nIGPDoWMgZ2nDoSB0cuG7iyBnaeG6o20gdHJvbmcgY8OhYyBub2RlIMSRxrDhu6NjIGNoaWEsIGPhu6dhIHThuqV0IGPhuqMgY8OhYyBjw6J5DQoNCmBgYHtyfQ0KIyBQbG90IGJp4buDdSDEkeG7kyB0aOG7gyBoaeG7h24gxJHhu5kgcXVhbiB0cuG7jW5nIGPhu6dhIGPDoWMgYmnhur9uDQp2YXJJbXBQbG90KHJmLmJvc3RvbikNCmBgYA0KDQoNCiMjIDIpIEJvb3RpbmcNCg0KDQoNCmBgYHtyfQ0KIyBMb2FkIHRoxrAgdmnhu4duIGdibQ0KbGlicmFyeShnYm0pDQpgYGANCg0KYGBge3J9DQojIHNldC5zZWVkIGTDuW5nIMSR4buDIHTDoWkgdOG6oW8gbmjhu69uZyB2ZWN0b3IgcmFuZG9tIGdp4buRbmcgbmhhdSB0aGVvIHTGsMahbmcg4bupbmcgduG7m2kgZ2nDoSB0cuG7iyDEkcaw4bujYyDEkcawYSB2w6BvIGjDoG0gc2VlZA0Kc2V0LnNlZWQoMSkNCiMgVOG6oW8gbcO0IGjDrG5oIGjhu5NpIHF1eSDhu5VuZyBxdWFuIGJvb3N0aW5nIHbhu5tpIGJp4bq/biDEkeG6p3UgcmEgbMOgIG1lZHYsIGJp4bq/biDEkeG6p3UgdsOgbyBsw6AgdOG6pXQgY+G6oyBjw6FjIGJp4bq/biBjw7JuIGzhuqFpLCB24bubaSBz4buRIGzGsOG7o25nIGPDonkgbMOgIDUwMDAsIMSR4buZIHPDonUgdOG7kWkgxJFhIGPhu6dhIGPDonkgbMOgIDQsIG3DtCBow6xuaCB0aGVvIHBow6JuIHBo4buRaSBnYXVzc2lhbg0KYm9vc3QuYm9zdG9uPWdibShtZWR2fi4sZGF0YT1Cb3N0b25bdHJhaW4sXSxkaXN0cmlidXRpb249ImdhdXNzaWFuIixuLnRyZWVzPTUwMDAsaW50ZXJhY3Rpb24uZGVwdGg9NCkNCmBgYA0KDQpgYGB7cn0NCiMgUGjDom4gdMOtY2ggbcO0IGjDrG5oIGJvb3N0aW5nIMSRxrDhu6NjIHThuqFvDQpzdW1tYXJ5KGJvb3N0LmJvc3RvbikNCmBgYA0KDQpIw6BtIHN1bW1hcnkoKSBjaG8gY2jDum5nIHRhIG3hu5l0IGLhuqNuZyB2w6AgMSBiaeG7g3UgxJHhu5MgY2hvIGJp4bq/dCBt4bupYyDEkeG7mSDhuqNuaCBoxrDhu59uZyBj4bunYSBjw6FjIGJp4bq/biwgdGEgdGjhuqV5IGJp4bq/biBybSBjw7MgbeG7qWMgxJHhu5kg4bqjbmggaMaw4bufbmcgY2FvIG5o4bqldCBsw6AgNDMuOTkxOTMyOQ0KDQoNCmBgYHtyfQ0KI0Jp4buDdSDEkeG7kyBwaMOibiB0w6FuIGPhu6dhIGPDoWMgYmnhur9uICBk4buvIGxp4buHdSB24bubaSBjw6FjIGThu68gbGnhu4d1IGPhu5l0IMSRxrDhu6NjIGNoaWEgdGjDoG5oIGPhu61hIHPhu5UgMXgyIGLhurFuZyBjw6FjaCBz4butIGThu6VuZyBow6BtIG1mcm93PWMoMSwyKSANCnBhcihtZnJvdz1jKDEsMikpDQojIEJp4buDdSDEkeG7kyBiaeG7g3UgZGnhu4VuIG3hu6ljIMSR4buZIOG6o25oIGjGsOG7n25nIGPhu6dhIGJp4bq/biBybQ0KcGxvdChib29zdC5ib3N0b24saT0icm0iKQ0KIyBCaeG7g3UgxJHhu5MgYmnhu4N1IGRp4buFbiBt4bupYyDEkeG7mSDhuqNuaCBoxrDhu59uZyBj4bunYSBiaeG6v24gbHN0YXQNCnBsb3QoYm9vc3QuYm9zdG9uLGk9ImxzdGF0IikNCmBgYA0KDQpgYGB7cn0NCiMgVGnhur9uIGjDoG5oIGThu7EgxJFvw6FuIHThuq1wIHRlc3QgbuG6sW0gbmdvw6BpIHThuq1wIHRyYWluIHbhu5tpIHPhu5EgbMaw4bujbmcgY8OieSA9IDUwMDANCnloYXQuYm9vc3Q9cHJlZGljdChib29zdC5ib3N0b24sbmV3ZGF0YT1Cb3N0b25bLXRyYWluLF0sbi50cmVlcz01MDAwKQ0KIyBUw61uaCBNZWFuIFNxdWFyZWQgRXJyb3IgKE1TRSkgZ2nhu69hIGdpw6EgdHLhu4sgZOG7sSDEkW/DoW4gdsOgIGdpw6EgdHLhu4sgdGjhuq10DQptZWFuKCh5aGF0LmJvb3N0LWJvc3Rvbi50ZXN0KV4yKQ0KYGBgDQoNCk1TRSBj4bunYSB04bqtcCB0ZXN0IGzDoCAgMTguODQ3MDkNCg0KYGBge3J9DQojIFThuqFvIG3DtCBow6xuaCBo4buTaSBxdXkg4buVbmcgcXVhbiBib29zdGluZyB24bubaSBiaeG6v24gxJHhuqd1IHJhIGzDoCBtZWR2LCBiaeG6v24gxJHhuqd1IHbDoG8gbMOgIHThuqV0IGPhuqMgY8OhYyBiaeG6v24gY8OybiBs4bqhaQ0KYm9vc3QuYm9zdG9uPWdibShtZWR2fi4sZGF0YT1Cb3N0b25bdHJhaW4sXSxkaXN0cmlidXRpb249ImdhdXNzaWFuIixuLnRyZWVzPTUwMDAsaW50ZXJhY3Rpb24uZGVwdGg9NCxzaHJpbmthZ2U9MC4yLHZlcmJvc2U9RikNCmBgYA0KDQotIE3DtCBow6xuaCBjw7Mgc+G7kSBsxrDhu6NuZyBjw6J5IGzDoCA1MDAwLCBwaMOibiBwaOG7kWkgZ2F1c3NpYW4sIMSR4buZIHPDonUgdGjhuqVwIG5o4bqldCBsw6AgNCwgbGVhcm5pbmcgcmF0ZSBt4buXaSBjw6J5IGzDoCAwLjIsIHZlcmJvc2UgPSBGOiBraMO0bmcgaW4gcmEgcXXDoSB0csOsbmggaHXhuqVuIGx1eeG7h24gbcO0IGjDrG5oDQoNCmBgYHtyfQ0KIyBUaeG6v24gaMOgbmggZOG7sSDEkW/DoW4gdOG6rXAgdGVzdCBu4bqxbSBuZ2/DoGkgdOG6rXAgdHJhaW4gduG7m2kgc+G7kSBsxrDhu6NuZyBjw6J5ID0gNTAwMA0KeWhhdC5ib29zdD1wcmVkaWN0KGJvb3N0LmJvc3RvbixuZXdkYXRhPUJvc3RvblstdHJhaW4sXSxuLnRyZWVzPTUwMDApDQojIFTDrW5oIE1lYW4gU3F1YXJlZCBFcnJvciAoTVNFKSBnaeG7r2EgZ2nDoSB0cuG7iyBk4buxIMSRb8OhbiB2w6AgZ2nDoSB0cuG7iyB0aOG6rXQNCm1lYW4oKHloYXQuYm9vc3QtYm9zdG9uLnRlc3QpXjIpDQpgYGANCg0KTVNFIGPhu6dhIHThuq1wIHRlc3QgbMOgICAxOC4zMzQ1NQ0K