Zadanie raport 5.

Opis zadania

Przetestowanie metod (regresja grzbietowa i lasso) oraz metod oceny (zestaw walidacyjny, walidacja krzyżowa) na zbiorze danych Wage z ISLR.

Skonfigurujmy nasze dane:

Wczytujemy dane:

library(ISLR)

data("Wage")
place<-Wage

Tworzymy wektor zmiennej wynikowej.

x = model.matrix(wage~., place)[,-1]
                                        
y = Wage %>%
  select(wage) %>%
  unlist() %>%
  as.numeric()

Regresja grzbietowa

Model regresji grzbietowej dla pełnych danych wygląda następująco:

grid = 10^seq(10, -2, length = 100)
ridge_mod = glmnet(x, y, alpha = 0, lambda = grid)
plot(ridge_mod) # wykres współczynników

dim(coef(ridge_mod))
## [1]  26 100
#Wymiar macierzy predyktorów

Uzyskana macierz jest macierzą wymiaru 26 na 100.

Dzielenie próbek

Podzielimy teraz próbki na zbiór treningowy i testowy w celu oszacowania błędu testu regresji grzbietowej i lasso.

set.seed(1)

train = Wage %>%
  sample_frac(0.5)

test = Wage %>%
  setdiff(train)

x_train = model.matrix(wage~., train)[,-1]
x_test = model.matrix(wage~., test)[,-1]

y_train = train %>%
  select(wage) %>%
  unlist() %>%
  as.numeric()

y_test = test %>%
  select(wage) %>%
  unlist() %>%
  as.numeric()

Wybierz lamdę, która minimalizuje treningowy MSE

set.seed(1)
cv.out = cv.glmnet(x_train, y_train, alpha = 0) 
# Dopasuj model regresji grzbietowej na danych treningowych
bestlam = cv.out$lambda.min  # Wybierz lamdę, która minimalizuje treningowy MSE 
bestlam
## [1] 3.939486

Wykres na podstawie najlepszej lambdy dla MSE

plot(cv.out)

Oszacowanie MSE

Następnie dopasowujemy model regresji grzbietowej na zbiorze treningowym i oceniamy jego MSE na zbiorze testowym, używając \(\lambda = bestlam\) . Czyli oszacowanie dla regresji z lambdą optymalną wyznaczoną wcześniej.

ridge_pred = predict(ridge_mod, s = bestlam, newx = x_test)
mean((ridge_pred - y_test)^2)
## [1] 169.468

Oszacowania współczynników

Ponownie wyznaczamy nasz model regresji grzbietowej na pełnym zestawie danych i sprawdzamy oszacowania współczynników.

out = glmnet(x, y, alpha = 0) # Dopasuj model regresji grzbietowej do pełnego zbioru danych
predict(out, type = "coefficients", s = bestlam)[1:10,] # Wyświetlanie współczynników przy użyciu lambda wybranego przez CV
##        (Intercept)               year                age   maritl2. Married 
##      -3.529273e+02       3.706173e-04       1.909890e-02       8.771868e-01 
##   maritl3. Widowed  maritl4. Divorced maritl5. Separated       race2. Black 
##      -2.610242e+00      -6.036440e-01      -9.351872e-01      -1.106809e+00 
##       race3. Asian       race4. Other 
##      -4.492573e-01      -4.079098e-01

Regresja OLS

Model kmnk dla s=0 (lambda równa 0) i oszacowanie MSE.

ridge_pred = predict(ridge_mod, s = 0, newx = x_test)

mean((ridge_pred - y_test)^2) # Oblicz testowe MSE
## [1] 151.514
lm(wage ~ year + age + maritl + race, data = train)
## 
## Call:
## lm(formula = wage ~ year + age + maritl + race, data = train)
## 
## Coefficients:
##        (Intercept)                year                 age    maritl2. Married  
##         -3038.2309              1.5526              0.5551             17.7962  
##   maritl3. Widowed   maritl4. Divorced  maritl5. Separated        race2. Black  
##             5.6667              1.8302              2.6743             -6.1402  
##       race3. Asian        race4. Other  
##             3.8241            -20.1080

Procedura Lasso

lasso_mod = glmnet(x_train, 
                   y_train, 
                   alpha = 1, 
                   lambda = grid) # Dopasuj model lasso do danych treningowych

plot(lasso_mod)    # Wykreśl współczynniki

Teraz przeprowadzimy walidację krzyżową i obliczymy związany z nią błąd testu i przedstawimy oszacowane MSE:

set.seed(1)
cv.out = cv.glmnet(x_train, y_train, alpha = 1) # Dopasuj model lasso do danych treningowych
plot(cv.out) # Narysuj wykres MSE dla próby uczącej jako funkcję lambda

MSE dla lambdy optymalnej i współczynniki regresji Lasso

Oszacowanie MSE testowego dla optymlanej lambdy przedstawia się następująco:

bestlam = cv.out$lambda.min # Wybierz lamdę, która minimalizuje MSE w próbie uczącej
lasso_pred = predict(lasso_mod, s = bestlam, newx = x_test) # Użyj najlepszej lambdy do przewidywania danych testowych
mean((lasso_pred - y_test)^2) # Oblicz MSE w próbie testowej
## [1] 154.8086

Teraz wyświetlone zostaną współczynniki regresji Lasso z lambdą optymalną.

out = glmnet(x, y, alpha = 1, lambda = grid) 
# Dopasuj model lasso do pełnego zbioru danych
lasso_coef = predict(out, type = "coefficients", s = bestlam)[1:10,] 
# Wyświetlanie współczynników przy użyciu lambda wybranego przez CV
lasso_coef
##        (Intercept)               year                age   maritl2. Married 
##      -4.075268e+02      -8.908553e-05      -3.182844e-05      -3.296052e-04 
##   maritl3. Widowed  maritl4. Divorced maritl5. Separated       race2. Black 
##       0.000000e+00       0.000000e+00       0.000000e+00       0.000000e+00 
##       race3. Asian       race4. Other 
##       0.000000e+00       0.000000e+00

Tylko cztery zmienne spośród badanych zmiennych nie przyjęły wartości zerowych, dlatego nie wszystkie zmienne są statystycznie istotne.

Zmienne istotne

Tylko niezerowe zmienne to:

lasso_coef[lasso_coef != 0] # Wyświetlanie tylko niezerowych współczynników
##      (Intercept)             year              age maritl2. Married 
##    -4.075268e+02    -8.908553e-05    -3.182844e-05    -3.296052e-04

Odpowiedzi na pytania:

  • Który zbiór danych wybrałeś?

Wybrany został zbiór danych “Wage” z biblioteki ISLR, czyli zależności płac.

  • Jaka była Twoja zmienna zależna (tzn. co próbowałeś modelować)?

Wage, czyli płaca.

  • Czy oczekiwałeś, że regresja grzbietowa będzie lepsza od lasso czy odwrotnie? Pokaż odpowiednie raporty, miary dopasowania i krótko je omów (porównaj).

Oczekiwaliśmy, że wyniki obu regresji będą podobne, jako iż regresja lasso oraz grzbietowa same w sobie podobne. Metoda lasso sama w swoich założeniach ma zwiększać dokładność przewidywań, w porównaniu do metody grzbietowej, dlatego wydaje się, że to właśnie ta pierwsza metoda jest lepsza. Wartość MSE w przypadku metody Lasso wychodzi niższa niż w przypadku metody grzbietowej.(175 - grzbietowa, do 155 - Lasso)

  • Jak wypada w stosunku do OLS?

W stosunku do OLS kilka zmiennych zostało wyzerowanych, zatem według Lasso selekcjonuje istotne zmienne.

  • Które predyktory okazały się ważne w ostatecznym modelu (modelach)?

W ostatecznym modelu istotne okazały się następujące predyktory : year, age, maritl2. Married, education2. HS Grad, education3. Some College education5., Advanced Degree

LS0tDQp0aXRsZTogIlJhcG9ydCA1LiINCmF1dGhvcjogIkthdGFyenluYSBMZXdjenVrLCBKdWxpdXN6IEFsZnV0aCwgUGlvdHIgV2ljaG93c2tpIg0KZGF0ZTogImByIFN5cy5EYXRlKClgIg0Kb3V0cHV0Og0KICBodG1sX2RvY3VtZW50Og0KICAgIHRoZW1lOiBjZXJ1bGVhbg0KICAgIGhpZ2hsaWdodDogdGV4dG1hdGUNCiAgICBmb250c2l6ZTogMTBwdA0KICAgIHRvYzogeWVzDQogICAgY29kZV9kb3dubG9hZDogeWVzDQogICAgdG9jX2Zsb2F0Og0KICAgICAgY29sbGFwc2VkOiBubw0KICAgIGRmX3ByaW50OiBkZWZhdWx0DQogICAgdG9jX2RlcHRoOiA1DQogIHBkZl9kb2N1bWVudDoNCiAgICB0b2M6IHllcw0KICAgIHRvY19kZXB0aDogJzUnDQpzdWJ0aXRsZTogUmVndWxhcnl6YWNqYQ0KZWRpdG9yX29wdGlvbnM6DQogIG1hcmtkb3duOg0KICAgIHdyYXA6IDcyDQotLS0NCg0KDQpgYGB7ciwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRSwgZWNobz1GQUxTRX0NCmxpYnJhcnkoSVNMUikNCmxpYnJhcnkoZ2xtbmV0KQ0KbGlicmFyeShkcGx5cikNCmxpYnJhcnkodGlkeXIpDQpgYGANCg0KIyMgWmFkYW5pZSByYXBvcnQgNS4NCg0KIyMgT3BpcyB6YWRhbmlhDQpQcnpldGVzdG93YW5pZSBtZXRvZCAocmVncmVzamEgZ3J6YmlldG93YSBpIGxhc3NvKSBvcmF6IG1ldG9kIG9jZW55ICh6ZXN0YXcgd2FsaWRhY3lqbnksIHdhbGlkYWNqYSBrcnp5xbxvd2EpIG5hIHpiaW9yemUgZGFueWNoIFdhZ2UgeiBJU0xSLg0KDQpTa29uZmlndXJ1am15IG5hc3plIGRhbmU6DQoNCldjenl0dWplbXkgZGFuZToNCmBgYHtyfQ0KbGlicmFyeShJU0xSKQ0KDQpkYXRhKCJXYWdlIikNCnBsYWNlPC1XYWdlDQpgYGANClR3b3J6eW15IHdla3RvciB6bWllbm5laiB3eW5pa293ZWouDQpgYGB7cn0NCnggPSBtb2RlbC5tYXRyaXgod2FnZX4uLCBwbGFjZSlbLC0xXQ0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIA0KeSA9IFdhZ2UgJT4lDQogIHNlbGVjdCh3YWdlKSAlPiUNCiAgdW5saXN0KCkgJT4lDQogIGFzLm51bWVyaWMoKQ0KYGBgDQoNCiMjIFJlZ3Jlc2phIGdyemJpZXRvd2ENCg0KTW9kZWwgcmVncmVzamkgZ3J6YmlldG93ZWogZGxhIHBlxYJueWNoIGRhbnljaCB3eWdsxIVkYSBuYXN0xJlwdWrEhWNvOg0KDQpgYGB7cn0NCmdyaWQgPSAxMF5zZXEoMTAsIC0yLCBsZW5ndGggPSAxMDApDQpyaWRnZV9tb2QgPSBnbG1uZXQoeCwgeSwgYWxwaGEgPSAwLCBsYW1iZGEgPSBncmlkKQ0KcGxvdChyaWRnZV9tb2QpICMgd3lrcmVzIHdzcMOzxYJjenlubmlrw7N3DQpgYGANCmBgYHtyfQ0KZGltKGNvZWYocmlkZ2VfbW9kKSkNCiNXeW1pYXIgbWFjaWVyenkgcHJlZHlrdG9yw7N3DQpgYGANClV6eXNrYW5hIG1hY2llcnogamVzdCBtYWNpZXJ6xIUgd3ltaWFydSAyNiBuYSAxMDAuDQoNCg0KIyMgRHppZWxlbmllIHByw7NiZWsNCg0KUG9kemllbGlteSB0ZXJheiBwcsOzYmtpIG5hIHpiacOzciB0cmVuaW5nb3d5IGkgdGVzdG93eSB3IGNlbHUgb3N6YWNvd2FuaWEgYsWCxJlkdSB0ZXN0dSByZWdyZXNqaSBncnpiaWV0b3dlaiBpIGxhc3NvLg0KDQpgYGB7cn0NCnNldC5zZWVkKDEpDQoNCnRyYWluID0gV2FnZSAlPiUNCiAgc2FtcGxlX2ZyYWMoMC41KQ0KDQp0ZXN0ID0gV2FnZSAlPiUNCiAgc2V0ZGlmZih0cmFpbikNCg0KeF90cmFpbiA9IG1vZGVsLm1hdHJpeCh3YWdlfi4sIHRyYWluKVssLTFdDQp4X3Rlc3QgPSBtb2RlbC5tYXRyaXgod2FnZX4uLCB0ZXN0KVssLTFdDQoNCnlfdHJhaW4gPSB0cmFpbiAlPiUNCiAgc2VsZWN0KHdhZ2UpICU+JQ0KICB1bmxpc3QoKSAlPiUNCiAgYXMubnVtZXJpYygpDQoNCnlfdGVzdCA9IHRlc3QgJT4lDQogIHNlbGVjdCh3YWdlKSAlPiUNCiAgdW5saXN0KCkgJT4lDQogIGFzLm51bWVyaWMoKQ0KYGBgDQoNCiMjIFd5YmllcnogbGFtZMSZLCBrdMOzcmEgbWluaW1hbGl6dWplIHRyZW5pbmdvd3kgTVNFDQoNCmBgYHtyfQ0Kc2V0LnNlZWQoMSkNCmN2Lm91dCA9IGN2LmdsbW5ldCh4X3RyYWluLCB5X3RyYWluLCBhbHBoYSA9IDApIA0KIyBEb3Bhc3VqIG1vZGVsIHJlZ3Jlc2ppIGdyemJpZXRvd2VqIG5hIGRhbnljaCB0cmVuaW5nb3d5Y2gNCmJlc3RsYW0gPSBjdi5vdXQkbGFtYmRhLm1pbiAgIyBXeWJpZXJ6IGxhbWTEmSwga3TDs3JhIG1pbmltYWxpenVqZSB0cmVuaW5nb3d5IE1TRSANCmJlc3RsYW0NCmBgYA0KV3lrcmVzIG5hIHBvZHN0YXdpZSBuYWpsZXBzemVqIGxhbWJkeSBkbGEgTVNFDQoNCmBgYHtyfQ0KcGxvdChjdi5vdXQpDQpgYGANCg0KDQojIyBPc3phY293YW5pZSBNU0UNCg0KTmFzdMSZcG5pZSBkb3Bhc293dWplbXkgbW9kZWwgcmVncmVzamkgZ3J6YmlldG93ZWogbmEgemJpb3J6ZSB0cmVuaW5nb3d5bSBpIG9jZW5pYW15IGplZ28gTVNFIG5hIHpiaW9yemUgdGVzdG93eW0sIHXFvHl3YWrEhWMgJFxsYW1iZGEgPSBiZXN0bGFtJCAuIEN6eWxpIG9zemFjb3dhbmllIGRsYSByZWdyZXNqaSB6IGxhbWJkxIUgb3B0eW1hbG7EhSB3eXpuYWN6b27EhSB3Y3plxZtuaWVqLg0KDQpgYGB7cn0NCnJpZGdlX3ByZWQgPSBwcmVkaWN0KHJpZGdlX21vZCwgcyA9IGJlc3RsYW0sIG5ld3ggPSB4X3Rlc3QpDQptZWFuKChyaWRnZV9wcmVkIC0geV90ZXN0KV4yKQ0KYGBgDQoNCiMjIE9zemFjb3dhbmlhIHdzcMOzxYJjenlubmlrw7N3DQoNClBvbm93bmllIHd5em5hY3phbXkgbmFzeiBtb2RlbCByZWdyZXNqaSBncnpiaWV0b3dlaiBuYSBwZcWCbnltIHplc3Rhd2llIGRhbnljaCBpIHNwcmF3ZHphbXkgb3N6YWNvd2FuaWEgd3Nww7PFgmN6eW5uaWvDs3cuDQoNCg0KYGBge3J9DQpvdXQgPSBnbG1uZXQoeCwgeSwgYWxwaGEgPSAwKSAjIERvcGFzdWogbW9kZWwgcmVncmVzamkgZ3J6YmlldG93ZWogZG8gcGXFgm5lZ28gemJpb3J1IGRhbnljaA0KcHJlZGljdChvdXQsIHR5cGUgPSAiY29lZmZpY2llbnRzIiwgcyA9IGJlc3RsYW0pWzE6MTAsXSAjIFd5xZt3aWV0bGFuaWUgd3Nww7PFgmN6eW5uaWvDs3cgcHJ6eSB1xbx5Y2l1IGxhbWJkYSB3eWJyYW5lZ28gcHJ6ZXogQ1YNCmBgYA0KDQojIyBSZWdyZXNqYSBPTFMNCg0KTW9kZWwga21uayBkbGEgcz0wIChsYW1iZGEgcsOzd25hIDApIGkgb3N6YWNvd2FuaWUgTVNFLg0KDQpgYGB7cn0NCnJpZGdlX3ByZWQgPSBwcmVkaWN0KHJpZGdlX21vZCwgcyA9IDAsIG5ld3ggPSB4X3Rlc3QpDQoNCm1lYW4oKHJpZGdlX3ByZWQgLSB5X3Rlc3QpXjIpICMgT2JsaWN6IHRlc3Rvd2UgTVNFDQpgYGANCg0KYGBge3J9DQpsbSh3YWdlIH4geWVhciArIGFnZSArIG1hcml0bCArIHJhY2UsIGRhdGEgPSB0cmFpbikNCmBgYA0KIyMgUHJvY2VkdXJhIExhc3NvDQoNCmBgYHtyIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9DQpsYXNzb19tb2QgPSBnbG1uZXQoeF90cmFpbiwgDQogICAgICAgICAgICAgICAgICAgeV90cmFpbiwgDQogICAgICAgICAgICAgICAgICAgYWxwaGEgPSAxLCANCiAgICAgICAgICAgICAgICAgICBsYW1iZGEgPSBncmlkKSAjIERvcGFzdWogbW9kZWwgbGFzc28gZG8gZGFueWNoIHRyZW5pbmdvd3ljaA0KDQpwbG90KGxhc3NvX21vZCkgICAgIyBXeWtyZcWbbCB3c3DDs8WCY3p5bm5pa2kNCmBgYA0KDQpUZXJheiBwcnplcHJvd2FkemlteSB3YWxpZGFjasSZIGtyennFvG93xIUgaSBvYmxpY3p5bXkgendpxIV6YW55IHogbmnEhSBixYLEhWQgdGVzdHUgaSBwcnplZHN0YXdpbXkgb3N6YWNvd2FuZSBNU0U6DQoNCg0KYGBge3J9DQpzZXQuc2VlZCgxKQ0KY3Yub3V0ID0gY3YuZ2xtbmV0KHhfdHJhaW4sIHlfdHJhaW4sIGFscGhhID0gMSkgIyBEb3Bhc3VqIG1vZGVsIGxhc3NvIGRvIGRhbnljaCB0cmVuaW5nb3d5Y2gNCnBsb3QoY3Yub3V0KSAjIE5hcnlzdWogd3lrcmVzIE1TRSBkbGEgcHLDs2J5IHVjesSFY2VqIGpha28gZnVua2NqxJkgbGFtYmRhDQpgYGANCg0KIyMgTVNFIGRsYSBsYW1iZHkgb3B0eW1hbG5laiBpIHdzcMOzxYJjenlubmlraSByZWdyZXNqaSBMYXNzbw0KDQpPc3phY293YW5pZSBNU0UgdGVzdG93ZWdvIGRsYSBvcHR5bWxhbmVqIGxhbWJkeSBwcnplZHN0YXdpYSBzacSZIG5hc3TEmXB1asSFY286DQoNCmBgYHtyfQ0KYmVzdGxhbSA9IGN2Lm91dCRsYW1iZGEubWluICMgV3liaWVyeiBsYW1kxJksIGt0w7NyYSBtaW5pbWFsaXp1amUgTVNFIHcgcHLDs2JpZSB1Y3rEhWNlag0KbGFzc29fcHJlZCA9IHByZWRpY3QobGFzc29fbW9kLCBzID0gYmVzdGxhbSwgbmV3eCA9IHhfdGVzdCkgIyBVxbx5aiBuYWpsZXBzemVqIGxhbWJkeSBkbyBwcnpld2lkeXdhbmlhIGRhbnljaCB0ZXN0b3d5Y2gNCm1lYW4oKGxhc3NvX3ByZWQgLSB5X3Rlc3QpXjIpICMgT2JsaWN6IE1TRSB3IHByw7NiaWUgdGVzdG93ZWoNCmBgYA0KDQoNClRlcmF6IHd5xZt3aWV0bG9uZSB6b3N0YW7EhSB3c3DDs8WCY3p5bm5pa2kgcmVncmVzamkgTGFzc28geiBsYW1iZMSFIG9wdHltYWxuxIUuDQpgYGB7cn0NCm91dCA9IGdsbW5ldCh4LCB5LCBhbHBoYSA9IDEsIGxhbWJkYSA9IGdyaWQpIA0KIyBEb3Bhc3VqIG1vZGVsIGxhc3NvIGRvIHBlxYJuZWdvIHpiaW9ydSBkYW55Y2gNCmxhc3NvX2NvZWYgPSBwcmVkaWN0KG91dCwgdHlwZSA9ICJjb2VmZmljaWVudHMiLCBzID0gYmVzdGxhbSlbMToxMCxdIA0KIyBXecWbd2lldGxhbmllIHdzcMOzxYJjenlubmlrw7N3IHByenkgdcW8eWNpdSBsYW1iZGEgd3licmFuZWdvIHByemV6IENWDQpsYXNzb19jb2VmDQpgYGANCg0KVHlsa28gY3p0ZXJ5IHptaWVubmUgc3BvxZtyw7NkIGJhZGFueWNoIHptaWVubnljaCBuaWUgcHJ6eWrEmcWCeSB3YXJ0b8WbY2kgemVyb3d5Y2gsIGRsYXRlZ28gbmllIHdzenlzdGtpZSB6bWllbm5lIHPEhSBzdGF0eXN0eWN6bmllIGlzdG90bmUuDQoNCiMjIFptaWVubmUgaXN0b3RuZQ0KDQpUeWxrbyBuaWV6ZXJvd2Ugem1pZW5uZSB0bzoNCmBgYHtyfQ0KbGFzc29fY29lZltsYXNzb19jb2VmICE9IDBdICMgV3nFm3dpZXRsYW5pZSB0eWxrbyBuaWV6ZXJvd3ljaCB3c3DDs8WCY3p5bm5pa8Ozdw0KYGBgDQoNCg0KDQoNCiMjIE9kcG93aWVkemkgbmEgcHl0YW5pYToNCg0KIC0gS3TDs3J5IHpiacOzciBkYW55Y2ggd3licmHFgmXFmz8NCg0KIFd5YnJhbnkgem9zdGHFgiB6YmnDs3IgZGFueWNoICJXYWdlIiB6IGJpYmxpb3Rla2kgSVNMUiwgY3p5bGkgemFsZcW8bm/Fm2NpIHDFgmFjLg0KIA0KIC0gSmFrYSBiecWCYSBUd29qYSB6bWllbm5hIHphbGXFvG5hICh0em4uIGNvIHByw7Nib3dhxYJlxZsgbW9kZWxvd2HEhyk/DQoNCiAgV2FnZSwgY3p5bGkgcMWCYWNhLiAgICANCiANCiAtIEN6eSBvY3pla2l3YcWCZcWbLCDFvGUgcmVncmVzamEgZ3J6YmlldG93YSBixJlkemllIGxlcHN6YSBvZCBsYXNzbyBjenkgb2R3cm90bmllPyBQb2thxbwgb2Rwb3dpZWRuaWUgcmFwb3J0eSwgbWlhcnkgZG9wYXNvd2FuaWEgaSBrcsOzdGtvIGplIG9tw7N3IChwb3LDs3duYWopLg0KIA0KIE9jemVraXdhbGnFm215LCDFvGUgd3luaWtpIG9idSByZWdyZXNqaSBixJlkxIUgcG9kb2JuZSwgamFrbyBpxbwgcmVncmVzamEgbGFzc28gb3JheiBncnpiaWV0b3dhIHNhbWUgdyBzb2JpZSBwb2RvYm5lLiBNZXRvZGEgbGFzc28gc2FtYSB3IHN3b2ljaCB6YcWCb8W8ZW5pYWNoIG1hIHp3acSZa3N6YcSHIGRva8WCYWRub8WbxIcgcHJ6ZXdpZHl3YcWELCB3IHBvcsOzd25hbml1IGRvIG1ldG9keSBncnpiaWV0b3dlaiwgZGxhdGVnbyB3eWRhamUgc2nEmSwgxbxlIHRvIHfFgmHFm25pZSB0YSBwaWVyd3N6YSBtZXRvZGEgamVzdCBsZXBzemEuDQogV2FydG/Fm8SHIE1TRSB3IHByenlwYWRrdSBtZXRvZHkgTGFzc28gd3ljaG9kemkgbmnFvHN6YSBuacW8IHcgcHJ6eXBhZGt1IG1ldG9keSBncnpiaWV0b3dlai4oMTc1IC0gZ3J6YmlldG93YSwgZG8gMTU1IC0gTGFzc28pDQogDQogLSBKYWsgd3lwYWRhIHcgc3Rvc3Vua3UgZG8gT0xTPw0KDQpXIHN0b3N1bmt1IGRvIE9MUyBraWxrYSB6bWllbm55Y2ggem9zdGHFgm8gd3l6ZXJvd2FueWNoLCB6YXRlbSB3ZWTFgnVnIExhc3NvIHNlbGVrY2pvbnVqZSBpc3RvdG5lIHptaWVubmUuDQogDQogLSBLdMOzcmUgcHJlZHlrdG9yeSBva2F6YcWCeSBzacSZIHdhxbxuZSB3IG9zdGF0ZWN6bnltIG1vZGVsdSAobW9kZWxhY2gpPw0KIA0KIFcgb3N0YXRlY3pueW0gbW9kZWx1IGlzdG90bmUgb2themHFgnkgc2nEmSBuYXN0xJlwdWrEhWNlIHByZWR5a3RvcnkgOiAgeWVhciwgYWdlLCBtYXJpdGwyLiBNYXJyaWVkLCBlZHVjYXRpb24yLiBIUyBHcmFkLCBlZHVjYXRpb24zLiBTb21lIENvbGxlZ2UgZWR1Y2F0aW9uNS4sIEFkdmFuY2VkIERlZ3JlZSAgDQogDQog