2) Phân tích, dự đoán, cách thức hoạt động một mô hình hồi quy đơn giản
# lm(medv~lstat) là hàm dùng để fit một mô hình hồi quy tuyến tính đơn giản với medv là giá trị đầu ra cần được dự đoán và lstat là giá trị đầu vào trong tập dữ liệu Boston
# Tuy nhiên hệ thống sẽ báo lỗi do R không nhận dạng được 2 biến medv và lstat
lm.fit=lm(medv~lstat)
Error in eval(predvars, data, env) : object 'medv' not found
# Do đó chúng ta cần truyền vào tập dữ liệu Boston để R có nhận dạng được 2 biến medv và lstat
# R đã nhận dạng được 2 biến medv và lstat trong dữ liệu Boston
lm.fit=lm(medv~lstat, data=Boston)
Dưới đây là cách không cần truyền vào tập dữ liệu Boston nhưng R vẫn có thể nhận dạng được các biến của dữ liệu
# attach dùng để khiến cho những biến feature trong dữ liệu có sẵn trong Rstudio theo tên
attach(Boston)
# Giờ đây hàm lm() vẫn có thể sử dụng được khi không cần truyền vào tập dữ liệu nào cả
lm.fit=lm(medv~lstat)
# Biến lm.fit dùng để hiển thị một số thông tin cơ bản về mô hình đầu ra như thông tin về hàm lm() đã sử dũng trước đó cũng như là những hệ số B0 = 34.55 và B1= -0.95 với medv = 34.55-0.95 lstat
lm.fit
Call:
lm(formula = medv ~ lstat)
Coefficients:
(Intercept) lstat
34.55 -0.95
# Và để hiển thị thông tin chi tiết hơn , chúng ta sử dụng hàm summary(lm.fit)
# Hàm sẽ cho chúng ta biết thông tin về p-values, thống kê t(t-statistic), độ lệch chuẩn cho những hệ số của biến lstat , cũng như là thống kê R^2, sai số chuẩn (standard errors) và thống kê F (F-statistic) cho mô hình
summary(lm.fit)
Call:
lm(formula = medv ~ lstat)
Residuals:
Min 1Q Median 3Q Max
-15.168 -3.990 -1.318 2.034 24.500
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) 34.55384 0.56263 61.41 <2e-16 ***
lstat -0.95005 0.03873 -24.53 <2e-16 ***
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
Residual standard error: 6.216 on 504 degrees of freedom
Multiple R-squared: 0.5441, Adjusted R-squared: 0.5432
F-statistic: 601.6 on 1 and 504 DF, p-value: < 2.2e-16
# Xem các biến được lưu trữ trong lm.fit
names(lm.fit)
[1] "coefficients" "residuals" "effects" "rank" "fitted.values" "assign"
[7] "qr" "df.residual" "xlevels" "call" "terms" "model"
# Xem giá trị của biến hệ số (coefficients) cho biết thông tin về B0 và B1
lm.fit$coefficients
(Intercept) lstat
34.5538409 -0.9500494
# Cũng được dùng để Xem giá trị của biến hệ số (coefficients) cho biết thông tin về B0 và B1
coef(lm.fit)
(Intercept) lstat
34.5538409 -0.9500494
# Hàm confint cho biết khoảng tin cậy của các hệ số B0 và B1 đang ước lượng
confint(lm.fit)
2.5 % 97.5 %
(Intercept) 33.448457 35.6592247
lstat -1.026148 -0.8739505
Hàm predict tạo ra khoảng tin cậy
# Cột fit là giá trị medv được dự đoán khi đưa vào dữ liệu (data) mới là biến lstat được gán cho 3 giá trị lần lượt là 5,10,15, lwr và upr là khoảng trên và khoảng dưới của khoảng tin cậy.
predict(lm.fit, data.frame(lstat=c(5,10,15)), interval="confidence")
fit lwr upr
1 29.80359 29.00741 30.59978
2 25.05335 24.47413 25.63256
3 20.30310 19.73159 20.87461
Hàm predict tạo ra khoảng dự đoán
# Cột fit là giá trị medv được dự đoán khi đưa vào dữ liệu (data) mới là biến lstat được gán cho 3 giá trị lần lượt là 5,10,15, lwr và upr là khoảng trên và khoảng dưới của khoảng dự đoán.
predict(lm.fit, data.frame(lstat=c(5,10,15)),
interval="prediction")
fit lwr upr
1 29.80359 17.565675 42.04151
2 25.05335 12.827626 37.27907
3 20.30310 8.077742 32.52846
3) Biểu đồ phân tán minh hoạ mô hình hồi quy đơn giản
# attach dùng để khiến cho những biến feature trong dữ liệu có sẵn trong Rstudio theo tên
attach(Boston)
The following objects are masked from Boston (pos = 3):
age, black, chas, crim, dis, indus, lstat, medv, nox, ptratio, rad, rm, tax, zn
The following objects are masked from Boston (pos = 4):
age, black, chas, crim, dis, indus, lstat, medv, nox, ptratio, rad, rm, tax, zn
The following objects are masked from Boston (pos = 5):
age, black, chas, crim, dis, indus, lstat, medv, nox, ptratio, rad, rm, tax, zn
The following objects are masked from Boston (pos = 6):
age, black, chas, crim, dis, indus, lstat, medv, nox, ptratio, rad, rm, tax, zn
The following objects are masked from Boston (pos = 7):
age, black, chas, crim, dis, indus, lstat, medv, nox, ptratio, rad, rm, tax, zn
# Hàm plot để tạo một đồ thị phân tán với giá trị đầu vào x= lstat và đầu ra y= medv
plot(lstat,medv)
# abline tạo ra 1 đường tuyến tính fit với mô hình hồi quy hiện tại với giá trị đầu vào là lstat và đầu ra là medv
abline(lm.fit)
# Điều chỉnh độ rộng hay độ dày của đường tuyến tính để chúng ta nhìn thấy đường thẳng rõ nét hơn
abline(lm.fit,lwd=3)

# Điều chỉnh độ rộng hay độ dày của đường tuyến tính để chúng ta nhìn thấy đường thẳng rõ nét hơn
plot(lstat,medv)
abline(lm.fit,lwd=3)

# Thay đổi màu sắc đường tuyến tính thành màu đỏ
plot(lstat,medv)
abline(lm.fit,lwd=3,col="red")

# Thay đổi các điểm dữ liệu của đồ thị phân tán thành màu xanh với đầu vào là lstat và đầu ra là medv
plot(lstat,medv,col="blue")

# Thay đổi hình dạng những điểm dữ liệu dưới dạng những viên đạn và có vòng tròn nhỏ hơn
plot(lstat,medv,pch=20)

# Thay đổi hình dạng những điểm dữ liệu những dấu +
plot(lstat,medv,pch="+")

# Biểu diễn những điểm dữ liệu với x và y từ 1->20 và hình dạng những điểm dữ liệu cũng thay đổi liên tục từ dạng 1->20
plot(1:20,1:20,pch=1:20)

#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ổ 2x2 bằng cách sử dụng hàm mfrow=c(2,2)
par(mfrow=c(2,2))
plot(lm.fit)

Biểu đồ 1 (Residuals vs Fitted) giúp quan sát những điểm giá trị được dự đoán(fit) và giá trị sai lệch dư thừa của những điểm dự đoán này so với những điểm thật
Biểu đồ 2 (Normal Q-Q) giúp so sánh 2 phân phối xác suất bằng cách vẽ các lượng tử của chúng với nhau
Biểu đồ 3 (Scale- Location) tương tự như biểu đồ 1 nhưng khác là lấy căn bậc 2 giá trị dư thừa chuẩn hoá
Biểu đồ 4 (Residuals vs Leverage) giúp phát hiện những ngoại lệ trong mô hình hồi quy đơn giản, cho phép quan sát sự lan rộng của những khoảng dư thừa thay đổi theo giá trị leverage( sự nhạy cảm của giá trị dự doán đối với sự thay đổi của những giá trị thật)
# Mô hình phân tán điểm dữ liệu được dự đoán và giá trị sai lệch dư thừa được tính từ mô hình hồi quy sử dụng hàm residuals()
plot(predict(lm.fit),residuals(lm.fit))

# Mô hình phân tán điểm dữ liệu được dự đoán và giá trị sai lệch dư thừa được tính từ phân phối student sử dụng hàm rstudent()
plot(predict(lm.fit),rstudent(lm.fit))

#Trên cơ sở các mô hình plot các giá trị dư thừa, có một số bằng chứng về phi tuyến tính. Thống kê đòn bẩy(leverage statistics) có thể được tính cho bất kỳ giá trị dự đoán nào bằng cách sử dụng Hàm hatvalues ()
plot(hatvalues(lm.fit))

# Chỉ mục cho chúng ta dòng nào có giá trị thống kê đòn đòn bẩy (leverage statistics) là lớn nhất
which.max(hatvalues(lm.fit))
375
375
LS0tDQp0aXRsZTogIk3DtCBow6xuaCBo4buTaSBxdXkgdHV54bq/biB0w61uaCDEkcahbiBnaeG6o24iDQpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sNCi0tLQ0KDQoNCiMjIyBUw6puOiBNYWkgSHV5DQojIyMgTVNTVjogNDMuMDEuMTA0LjA2NQ0KIyMjIFPhu5EgdGjhu6kgdOG7sTogMDgNCg0KIyAxKSBOaOG6rXAgdGjGsCB2aeG7h24gdsOgIHTDrG0gaGnhu4N1IHThuq1wIGThu68gbGnhu4d1DQoNCmBgYHtyfQ0KIyBMb2FkIHRoxrAgdmnhu4duIE1hc3MgY2jhu6lhIHThuq1wIGThu68gbGnhu4d1IEJvc3Rvbg0KbGlicmFyeShNQVNTKQ0KIyBMaeG7h3Qga8OqIHTDqm4gY8OhYyBiaeG6v24gdGh14buZYyB0w61uaCBj4bunYSBk4buvIGxp4buHdSBCb3N0b24NCm5hbWVzKEJvc3RvbikNCiMgVMOsbSBoaeG7g3UgdGjDqm0gduG7gSB0aMO0bmcgdGluIHThuq1wIGThu68gbGnhu4d1IEJvc3Rvbg0KP0Jvc3Rvbg0KDQpgYGANCg0KU+G7rSBk4bulbmcgY8OidSBs4buHbmggP0Jvc3RvbiBnacO6cCBjaMO6bmcgdGEgdMOsbSBoaeG7g3UgcsO1IGjGoW4gduG7gSBjw6FjIGJp4bq/biB0aHXhu5ljIHTDrW5oIHRyb25nIGThu68gbGnhu4d1IEJvc3RvbiAoY8OzIDUwNiBkw7JuZyB2w6AgMTQgY+G7mXQpLCBjaOG6s25nIGjhuqFuIG5oxrAgbMOgOg0KDQogIC0gbWVkdiBsw6AgZ2nDoSB0cuG7iyBuaMOgIGPhu61hIHRydW5nIGLDrG5oDQogIA0KICAtIHJtIGzDoCBz4buRIHBow7JuZyB0cnVuZyBiw6xuaCBt4buXaSBuaMOgDQogIA0KICAtIGFnZSBsw6AgdHJ1bmcgYsOsbmggxJHhu5kgdHXhu5VpIGPhu6dhIGPDoWMgY8SDbiBuaMOgDQogIA0KICAtIGxzdGF0IGzDoCB04buJIGzhu4cgaOG7mSBnaWEgxJHDrG5oIGPDsyDEkeG7i2EgduG7iyBraW5oIHThur8geMOjIGjhu5lpIHRo4bqlcA0KDQoNCiMgMikgUGjDom4gdMOtY2gsIGThu7EgxJFvw6FuLCBjw6FjaCB0aOG7qWMgaG/huqF0IMSR4buZbmcgbeG7mXQgbcO0IGjDrG5oIGjhu5NpIHF1eSDEkcahbiBnaeG6o24NCg0KDQpgYGB7cn0NCiMgbG0obWVkdn5sc3RhdCkgbMOgIGjDoG0gZMO5bmcgxJHhu4MgZml0IG3hu5l0IG3DtCBow6xuaCBo4buTaSBxdXkgdHV54bq/biB0w61uaCDEkcahbiBnaeG6o24gduG7m2kgbWVkdiBsw6AgZ2nDoSB0cuG7iyDEkeG6p3UgcmEgY+G6p24gxJHGsOG7o2MgZOG7sSDEkW/DoW4gIHbDoCBsc3RhdCBsw6AgZ2nDoSB0cuG7iyDEkeG6p3UgdsOgbyB0cm9uZyB04bqtcCBk4buvIGxp4buHdSBCb3N0b24NCiMgVHV5IG5oacOqbiBo4buHIHRo4buRbmcgc+G6vSBiw6FvIGzhu5dpIGRvIFIga2jDtG5nIG5o4bqtbiBk4bqhbmcgxJHGsOG7o2MgMiBiaeG6v24gbWVkdiB2w6AgbHN0YXQgDQpsbS5maXQ9bG0obWVkdn5sc3RhdCkNCmBgYA0KDQoNCg0KYGBge3J9DQojIERvIMSRw7MgY2jDum5nIHRhIGPhuqduIHRydXnhu4FuIHbDoG8gdOG6rXAgZOG7ryBsaeG7h3UgQm9zdG9uIMSR4buDIFIgY8OzIG5o4bqtbiBk4bqhbmcgxJHGsOG7o2MgMiBiaeG6v24gbWVkdiB2w6AgbHN0YXQNCiMgUiDEkcOjIG5o4bqtbiBk4bqhbmcgxJHGsOG7o2MgMiBiaeG6v24gbWVkdiB2w6AgbHN0YXQgdHJvbmcgZOG7ryBsaeG7h3UgQm9zdG9uDQpsbS5maXQ9bG0obWVkdn5sc3RhdCwgZGF0YT1Cb3N0b24pDQpgYGANCg0KIyMjIETGsOG7m2kgxJHDonkgbMOgIGPDoWNoIGtow7RuZyBj4bqnbiB0cnV54buBbiB2w6BvIHThuq1wIGThu68gbGnhu4d1IEJvc3RvbiBuaMawbmcgUiB24bqrbiBjw7MgdGjhu4Mgbmjhuq1uIGThuqFuZyDEkcaw4bujYyBjw6FjIGJp4bq/biBj4bunYSBk4buvIGxp4buHdQ0KDQpgYGB7cn0NCiMgYXR0YWNoIGTDuW5nIMSR4buDIGtoaeG6v24gY2hvIG5o4buvbmcgYmnhur9uIGZlYXR1cmUgdHJvbmcgZOG7ryBsaeG7h3UgY8OzIHPhurVuIHRyb25nIFJzdHVkaW8gdGhlbyB0w6puDQphdHRhY2goQm9zdG9uKQ0KIyBHaeG7nSDEkcOieSBow6BtIGxtKCkgduG6q24gY8OzIHRo4buDIHPhu60gZOG7pW5nIMSRxrDhu6NjIGtoaSBraMO0bmcgY+G6p24gdHJ1eeG7gW4gdsOgbyB04bqtcCBk4buvIGxp4buHdSBuw6BvIGPhuqMgDQpsbS5maXQ9bG0obWVkdn5sc3RhdCkNCmBgYA0KDQoNCmBgYHtyfQ0KIyBCaeG6v24gbG0uZml0IGTDuW5nIMSR4buDIGhp4buDbiB0aOG7iyBt4buZdCBz4buRIHRow7RuZyB0aW4gY8ahIGLhuqNuIHbhu4EgbcO0IGjDrG5oIMSR4bqndSByYSBuaMawIHRow7RuZyB0aW4gduG7gSBow6BtIGxtKCkgxJHDoyBz4butIGTFqW5nIHRyxrDhu5tjIMSRw7MgY8WpbmcgbmjGsCBsw6Agbmjhu69uZyBo4buHIHPhu5EgQjAgPSAzNC41NSB2w6AgQjE9IC0wLjk1IHbhu5tpIG1lZHYgPSAzNC41NS0wLjk1IGxzdGF0DQpsbS5maXQNCmBgYA0KDQpgYGB7cn0NCiMgVsOgIMSR4buDIGhp4buDbiB0aOG7iyB0aMO0bmcgdGluIGNoaSB0aeG6v3QgaMahbiAsIGNow7puZyB0YSBz4butIGThu6VuZyBow6BtIHN1bW1hcnkobG0uZml0KQ0KIyBIw6BtIHPhur0gY2hvIGNow7puZyB0YSBiaeG6v3QgdGjDtG5nIHRpbiB24buBIHAtdmFsdWVzLCB0aOG7kW5nIGvDqiB0KHQtc3RhdGlzdGljKSwgxJHhu5kgbOG7h2NoIGNodeG6qW4gY2hvIG5o4buvbmcgaOG7hyBz4buRIGPhu6dhIGJp4bq/biBsc3RhdCAsIGPFqW5nIG5oxrAgbMOgIHRo4buRbmcga8OqIFJeMiwgc2FpIHPhu5EgY2h14bqpbiAoc3RhbmRhcmQgZXJyb3JzKSB2w6AgdGjhu5FuZyBrw6ogRiAoRi1zdGF0aXN0aWMpIGNobyBtw7QgaMOsbmgNCnN1bW1hcnkobG0uZml0KQ0KYGBgDQoNCmBgYHtyfQ0KIyBYZW0gY8OhYyBiaeG6v24gxJHGsOG7o2MgbMawdSB0cuG7ryB0cm9uZyBsbS5maXQNCm5hbWVzKGxtLmZpdCkNCiMgWGVtIGdpw6EgdHLhu4sgY+G7p2EgYmnhur9uIGjhu4cgc+G7kSAoY29lZmZpY2llbnRzKSBjaG8gYmnhur90IHRow7RuZyB0aW4gduG7gSBCMCB2w6AgQjENCmxtLmZpdCRjb2VmZmljaWVudHMNCmBgYA0KDQpgYGB7cn0NCiMgQ8WpbmcgxJHGsOG7o2MgZMO5bmcgxJHhu4MgWGVtIGdpw6EgdHLhu4sgY+G7p2EgYmnhur9uIGjhu4cgc+G7kSAoY29lZmZpY2llbnRzKSBjaG8gYmnhur90IHRow7RuZyB0aW4gduG7gSBCMCB2w6AgQjENCmNvZWYobG0uZml0KQ0KYGBgDQoNCmBgYHtyfQ0KIyBIw6BtIGNvbmZpbnQgY2hvIGJp4bq/dCBraG/huqNuZyB0aW4gY+G6rXkgY+G7p2EgY8OhYyBo4buHIHPhu5EgQjAgdsOgIEIxIMSRYW5nIMaw4bubYyBsxrDhu6NuZw0KY29uZmludChsbS5maXQpDQpgYGANCg0KIyMjIEjDoG0gcHJlZGljdCB04bqhbyByYSBraG/huqNuZyB0aW4gY+G6rXkgDQoNCmBgYHtyfQ0KIyBD4buZdCBmaXQgbMOgIGdpw6EgdHLhu4sgbWVkdiDEkcaw4bujYyBk4buxIMSRb8OhbiBraGkgxJHGsGEgdsOgbyBk4buvIGxp4buHdSAoZGF0YSkgbeG7m2kgbMOgIGJp4bq/biBsc3RhdCDEkcaw4bujYyBnw6FuIGNobyAzIGdpw6EgdHLhu4sgbOG6p24gbMaw4bujdCBsw6AgNSwxMCwxNSwgbHdyIHbDoCB1cHIgbMOgIGtob+G6o25nIHRyw6puIHbDoCBraG/huqNuZyBkxrDhu5tpIGPhu6dhIGtob+G6o25nIHRpbiBj4bqteS4NCnByZWRpY3QobG0uZml0LCBkYXRhLmZyYW1lKGxzdGF0PWMoNSwxMCwxNSkpLCBpbnRlcnZhbD0iY29uZmlkZW5jZSIpDQpgYGANCg0KIyMjIEjDoG0gcHJlZGljdCB04bqhbyByYSBraG/huqNuZyBk4buxIMSRb8Ohbg0KDQpgYGB7cn0NCiMgQ+G7mXQgZml0IGzDoCBnacOhIHRy4buLIG1lZHYgxJHGsOG7o2MgZOG7sSDEkW/DoW4ga2hpIMSRxrBhIHbDoG8gZOG7ryBsaeG7h3UgKGRhdGEpIG3hu5tpIGzDoCBiaeG6v24gbHN0YXQgxJHGsOG7o2MgZ8OhbiBjaG8gMyBnacOhIHRy4buLIGzhuqduIGzGsOG7o3QgbMOgIDUsMTAsMTUsIGx3ciB2w6AgdXByIGzDoCBraG/huqNuZyB0csOqbiB2w6Aga2hv4bqjbmcgZMaw4bubaSBj4bunYSBraG/huqNuZyBk4buxIMSRb8Ohbi4NCnByZWRpY3QobG0uZml0LCBkYXRhLmZyYW1lKGxzdGF0PWMoNSwxMCwxNSkpLA0KaW50ZXJ2YWw9InByZWRpY3Rpb24iKQ0KYGBgDQoNCiMgMykgQmnhu4N1IMSR4buTIHBow6JuIHTDoW4gbWluaCBob+G6oSBtw7QgaMOsbmggaOG7k2kgcXV5IMSRxqFuIGdp4bqjbg0KDQpgYGB7cn0NCiMgYXR0YWNoIGTDuW5nIMSR4buDIGtoaeG6v24gY2hvIG5o4buvbmcgYmnhur9uIGZlYXR1cmUgdHJvbmcgZOG7ryBsaeG7h3UgY8OzIHPhurVuIHRyb25nIFJzdHVkaW8gdGhlbyB0w6puDQphdHRhY2goQm9zdG9uKQ0KIyBIw6BtIHBsb3QgxJHhu4MgdOG6oW8gbeG7mXQgxJHhu5MgdGjhu4sgcGjDom4gdMOhbiB24bubaSBnacOhIHRy4buLIMSR4bqndSB2w6BvIHg9IGxzdGF0IHbDoCDEkeG6p3UgcmEgeT0gbWVkdg0KcGxvdChsc3RhdCxtZWR2KQ0KIyBhYmxpbmUgdOG6oW8gcmEgMSDEkcaw4budbmcgdHV54bq/biB0w61uaCBmaXQgduG7m2kgbcO0IGjDrG5oIGjhu5NpIHF1eSBoaeG7h24gdOG6oWkgduG7m2kgZ2nDoSB0cuG7iyDEkeG6p3UgdsOgbyBsw6AgbHN0YXQgdsOgIMSR4bqndSByYSBsw6AgbWVkdg0KYWJsaW5lKGxtLmZpdCkNCiMgxJBp4buBdSBjaOG7iW5oIMSR4buZIHLhu5luZyBoYXkgxJHhu5kgZMOgeSBj4bunYSDEkcaw4budbmcgdHV54bq/biB0w61uaCDEkeG7gyBjaMO6bmcgdGEgbmjDrG4gdGjhuqV5IMSRxrDhu51uZyB0aOG6s25nIHLDtSBuw6l0IGjGoW4NCmFibGluZShsbS5maXQsbHdkPTMpDQojIMSQaeG7gXUgY2jhu4luaCBtw6B1IHNhbg0KDQpgYGANCg0KYGBge3J9DQojIMSQaeG7gXUgY2jhu4luaCDEkeG7mSBy4buZbmcgaGF5IMSR4buZIGTDoHkgY+G7p2EgxJHGsOG7nW5nIHR1eeG6v24gdMOtbmggPTMgxJHhu4MgY2jDum5nIHRhIG5ow6xuIHRo4bqleSDEkcaw4budbmcgdGjhurNuZyByw7UgbsOpdCBoxqFuDQpwbG90KGxzdGF0LG1lZHYpDQphYmxpbmUobG0uZml0LGx3ZD0zKQ0KYGBgDQoNCmBgYHtyfQ0KIyBUaGF5IMSR4buVaSBtw6B1IHPhuq9jIMSRxrDhu51uZyB0dXnhur9uIHTDrW5oIHRow6BuaCBtw6B1IMSR4buPDQpwbG90KGxzdGF0LG1lZHYpDQphYmxpbmUobG0uZml0LGx3ZD0zLGNvbD0icmVkIikNCmBgYA0KDQpgYGB7cn0NCiMgVGhheSDEkeG7lWkgY8OhYyDEkWnhu4NtIGThu68gbGnhu4d1IGPhu6dhIMSR4buTIHRo4buLIHBow6JuIHTDoW4gdGjDoG5oIG3DoHUgeGFuaCB24bubaSDEkeG6p3UgdsOgbyBsw6AgbHN0YXQgdsOgIMSR4bqndSByYSBsw6AgbWVkdiANCnBsb3QobHN0YXQsbWVkdixjb2w9ImJsdWUiKQ0KIyBUaGF5IMSR4buVaSBow6xuaCBk4bqhbmcgbmjhu69uZyDEkWnhu4NtIGThu68gbGnhu4d1IGTGsOG7m2kgZOG6oW5nIG5o4buvbmcgdmnDqm4gxJHhuqFuIHbDoCBjw7MgdsOybmcgdHLDsm4gbmjhu48gaMahbg0KcGxvdChsc3RhdCxtZWR2LHBjaD0yMCkNCiMgVGhheSDEkeG7lWkgaMOsbmggZOG6oW5nIG5o4buvbmcgxJFp4buDbSBk4buvIGxp4buHdSBuaOG7r25nIGThuqV1ICsgDQpwbG90KGxzdGF0LG1lZHYscGNoPSIrIikNCiMgQmnhu4N1IGRp4buFbiBuaOG7r25nIMSRaeG7g20gZOG7ryBsaeG7h3UgduG7m2kgeCB2w6AgeSB04burIDEtPjIwIHbDoCBow6xuaCBk4bqhbmcgbmjhu69uZyDEkWnhu4NtIGThu68gbGnhu4d1IGPFqW5nIHRoYXkgxJHhu5VpIGxpw6puIHThu6VjIHThu6sgZOG6oW5nIDEtPjIwDQpwbG90KDE6MjAsMToyMCxwY2g9MToyMCkNCmBgYA0KDQoNCmBgYHtyfQ0KI0Jp4buDdSDEkeG7kyBwaMOibiB0w6FuIGPhu6dhIGPDoWMgYmnhur9uICBk4buvIGxp4buHdSB24bubaSBjw6FjIGThu68gbGnhu4d1IGPhu5l0IMSRxrDhu6NjIGNoaWEgdGjDoG5oIGPhu61hIHPhu5UgMngyIGLhurFuZyBjw6FjaCBz4butIGThu6VuZyBow6BtIG1mcm93PWMoMiwyKQ0KcGFyKG1mcm93PWMoMiwyKSkNCiMgUGxvdCA0IGJp4buDdSDEkeG7kyBjaOG6qW4gxJFvw6FuIA0KcGxvdChsbS5maXQpDQpgYGANCg0KLSBCaeG7g3UgxJHhu5MgMSAoUmVzaWR1YWxzIHZzIEZpdHRlZCkgZ2nDunAgcXVhbiBzw6F0IG5o4buvbmcgxJFp4buDbSBnacOhIHRy4buLIMSRxrDhu6NjIGThu7EgxJFvw6FuKGZpdCkgdsOgIGdpw6EgdHLhu4sgc2FpIGzhu4djaCBkxrAgdGjhu6thIGPhu6dhIG5o4buvbmcgxJFp4buDbSBk4buxIMSRb8OhbiBuw6B5IHNvIHbhu5tpIG5o4buvbmcgxJFp4buDbSB0aOG6rXQNCg0KLSBCaeG7g3UgxJHhu5MgMiAoTm9ybWFsIFEtUSkgZ2nDunAgc28gc8OhbmggMiBwaMOibiBwaOG7kWkgeMOhYyBzdeG6pXQgYuG6sW5nIGPDoWNoIHbhur0gY8OhYyBsxrDhu6NuZyB04butIGPhu6dhIGNow7puZyB24bubaSBuaGF1IA0KDQotIEJp4buDdSDEkeG7kyAzIChTY2FsZS0gTG9jYXRpb24pIHTGsMahbmcgdOG7sSBuaMawIGJp4buDdSDEkeG7kyAxIG5oxrBuZyBraMOhYyBsw6AgbOG6pXkgY8SDbiBi4bqtYyAyIGdpw6EgdHLhu4sgZMawIHRo4burYSBjaHXhuqluIGhvw6ENCg0KLSBCaeG7g3UgxJHhu5MgNCAoUmVzaWR1YWxzIHZzIExldmVyYWdlKSBnacO6cCBwaMOhdCBoaeG7h24gbmjhu69uZyBuZ2/huqFpIGzhu4cgdHJvbmcgbcO0IGjDrG5oIGjhu5NpIHF1eSDEkcahbiBnaeG6o24sIGNobyBwaMOpcCBxdWFuIHPDoXQgc+G7sSBsYW4gcuG7mW5nIGPhu6dhIG5o4buvbmcga2hv4bqjbmcgZMawIHRo4burYSB0aGF5IMSR4buVaSB0aGVvIGdpw6EgdHLhu4sgbGV2ZXJhZ2UoIHPhu7EgbmjhuqF5IGPhuqNtIGPhu6dhIGdpw6EgdHLhu4sgZOG7sSBkb8OhbiDEkeG7kWkgduG7m2kgc+G7sSB0aGF5IMSR4buVaSBj4bunYSBuaOG7r25nIGdpw6EgdHLhu4sgdGjhuq10KQ0KDQpgYGB7cn0NCiMgTcO0IGjDrG5oIHBow6JuIHTDoW4gxJFp4buDbSBk4buvIGxp4buHdSDEkcaw4bujYyBk4buxIMSRb8OhbiB2w6AgZ2nDoSB0cuG7iyBzYWkgbOG7h2NoIGTGsCB0aOG7q2EgxJHGsOG7o2MgdMOtbmggdOG7qyBtw7QgaMOsbmggaOG7k2kgcXV5IHPhu60gZOG7pW5nIGjDoG0gcmVzaWR1YWxzKCkNCnBsb3QocHJlZGljdChsbS5maXQpLHJlc2lkdWFscyhsbS5maXQpKQ0KYGBgDQoNCmBgYHtyfQ0KIyBNw7QgaMOsbmggcGjDom4gdMOhbiDEkWnhu4NtIGThu68gbGnhu4d1IMSRxrDhu6NjIGThu7EgxJFvw6FuIHbDoCBnacOhIHRy4buLIHNhaSBs4buHY2ggZMawIHRo4burYSDEkcaw4bujYyB0w61uaCB04burIHBow6JuIHBo4buRaSBzdHVkZW50IHPhu60gZOG7pW5nIGjDoG0gcnN0dWRlbnQoKQ0KcGxvdChwcmVkaWN0KGxtLmZpdCkscnN0dWRlbnQobG0uZml0KSkNCmBgYA0KDQpgYGB7cn0NCiNUcsOqbiBjxqEgc+G7nyBjw6FjIG3DtCBow6xuaCBwbG90IGPDoWMgZ2nDoSB0cuG7iyBkxrAgdGjhu6thLCBjw7MgbeG7mXQgc+G7kSBi4bqxbmcgY2jhu6luZyB24buBIHBoaSB0dXnhur9uIHTDrW5oLiBUaOG7kW5nIGvDqiDEkcOybiBi4bqpeShsZXZlcmFnZSBzdGF0aXN0aWNzKSBjw7MgdGjhu4MgxJHGsOG7o2MgdMOtbmggY2hvIGLhuqV0IGvhu7MgZ2nDoSB0cuG7iyBk4buxIMSRb8OhbiBuw6BvIGLhurFuZyBjw6FjaCBz4butIGThu6VuZyBIw6BtIGhhdHZhbHVlcyALCygpDQpwbG90KGhhdHZhbHVlcyhsbS5maXQpKQ0KYGBgDQoNCmBgYHtyfQ0KIyBDaOG7iSBt4bulYyBjaG8gY2jDum5nIHRhIGTDsm5nIG7DoG8gY8OzIGdpw6EgdHLhu4sgdGjhu5FuZyBrw6ogxJHDsm4gxJHDsm4gYuG6qXkgKGxldmVyYWdlIHN0YXRpc3RpY3MpIGzDoCBs4bubbiBuaOG6pXQNCndoaWNoLm1heChoYXR2YWx1ZXMobG0uZml0KSkNCmBgYA0KDQo=