Prerequisites

Để sử dụng được Apache Spark cần cài đặt:

  1. Cài đặt Java JDK.
  2. R + R Studio.
  3. Thư viện sparklyr.

Sau khi cài đặt xong kiểm tra một số thông tin về phiên bản:

library(sparklyr)
spark_installed_versions()
##   spark hadoop                                                              dir
## 1 2.4.3    2.7 C:\\Users\\Admin\\AppData\\Local/spark/spark-2.4.3-bin-hadoop2.7

Như vậy Spark (Version 2.4.3) và Hadoop (Version 2.7) cũng được install trên local machine.

Connecting

Giả sử rằng việc cài đặt và thiết lập môi trường để sử dụng Apache Spark (gọi tắt là Spark) đã được hoàn thành. Các chương sau sẽ giải thích việc tìm, cài đặt và kết nối nhiều Spark Cluster trên nhiều máy tính khác nhau. Với mục đính minh họa, chương này tập trung vào vận hành code trên local cluster (máy tính cá nhân).

Để kết nối với local cluster trên máy tính cá nhân thực hiện R codes dưới đây:

sc <- spark_connect(master = "local", version = "2.4.3")

Chúng ta có thể xem thêm một số thông tin khác về local cluster bằng lệnh sau:

sc

Sử dụng Apache Spark

Sau khi kết nối với local cluster chúng ta sử dụng bộ dữ liệu mtcars (có săn trong R Environment) để minh họa. Trước hết xem qua bộ dữ liệu này:

head(mtcars)
##                    mpg cyl disp  hp drat    wt  qsec vs am gear carb
## Mazda RX4         21.0   6  160 110 3.90 2.620 16.46  0  1    4    4
## Mazda RX4 Wag     21.0   6  160 110 3.90 2.875 17.02  0  1    4    4
## Datsun 710        22.8   4  108  93 3.85 2.320 18.61  1  1    4    1
## Hornet 4 Drive    21.4   6  258 110 3.08 3.215 19.44  1  0    3    1
## Hornet Sportabout 18.7   8  360 175 3.15 3.440 17.02  0  0    3    2
## Valiant           18.1   6  225 105 2.76 3.460 20.22  1  0    3    1

Lưu lại bộ dữ liệu này ở định dạng .csv để sử dụng sau này nếu cần thiết:

write.csv(mtcars, "cars.csv", row.names = FALSE)

Sử dụng lệnh copy_to() để copy bộ dữ liệu mtcars từ môi trường R vào Apache Spark:

cars <- copy_to(sc, mtcars)

Chúng ta có thể access bộ dữ liệu này thông qua R. Ví dụ:

head(cars)
## # Source: spark<?> [?? x 11]
##     mpg   cyl  disp    hp  drat    wt  qsec    vs    am  gear  carb
##   <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
## 1  21       6   160   110  3.9   2.62  16.5     0     1     4     4
## 2  21       6   160   110  3.9   2.88  17.0     0     1     4     4
## 3  22.8     4   108    93  3.85  2.32  18.6     1     1     4     1
## 4  21.4     6   258   110  3.08  3.22  19.4     1     0     3     1
## 5  18.7     8   360   175  3.15  3.44  17.0     0     0     3     2
## 6  18.1     6   225   105  2.76  3.46  20.2     1     0     3     1

Web Interface

Hầu hết Spark commands được thực hiện từ Rstudio/R console. Tuy nhiên việc theo dõi (và các quá trình khác) được thực hiện thông qua giao diện Web của Spark. Giao diện này là môt web application được cung cấp bởi Spark bằng cách thực hiện lệnh sau:

spark_web(sc)

Kết quả sẽ như dưới đây:

# Data Query and Manipulation

Khi sử dụng Spark thông qua R chúng ta có thể sử dụng các ngôn ngữ truy vấn dữ liệu. Chẳng hạn sử dụng SQL để đếm số dòng:

library(DBI)
dbGetQuery(sc, "SELECT count(*) FROM mtcars")
##   count(1)
## 1       32

Hoặc sử dụng các hàm của thư viện dplyr:

library(dplyr)

cars %>% 
  group_by(cyl) %>% 
  count(sort = TRUE)
## # Source:     spark<?> [?? x 2]
## # Ordered by: desc(n)
##     cyl     n
##   <dbl> <dbl>
## 1     8    14
## 2     4    11
## 3     6     7

Modelling

Sau khi load bộ dữ liệu mtcars vào Spark Environment chúng ta có thể, ví dụ, đánh giá tác động của horsepower lên fuel efficiency thông qua hồi quy:

model <- ml_linear_regression(cars, mpg ~ hp)

Với mô hình đã huấn luyện xong chúng ta có thể sử dụng mô hình này để dự báo mức độ fuel efficiency của, ví dụ, ba quan sát với horsepower lần lượt là 250, 260 và 270 như sau:

# Some data points: 
my_df <- data.frame(hp = c(250, 260, 270))

# Load to Spark environment: 
my_df_spark <- copy_to(sc, my_df)

# Use trained model for predicting: 
ml_predict(model, my_df_spark) -> mpg_predicted

# Show results: 
mpg_predicted 
## # Source: spark<?> [?? x 2]
##      hp prediction
##   <dbl>      <dbl>
## 1   250       13.0
## 2   260       12.4
## 3   270       11.7

OK. Chúc mừng bạn. Bạn vừa sử dụng mô hình train được bằng Spark để đưa ra các giá trị dự báo lần lượt là 13.0, 12.4 và 11.7. Thực tế thì việc huấn luyện các mô hình học máy sẽ còn nhiều bước và công đoạn hơn toy example vừa trình bày ở trên. Những điều này sẽ được trình bày trong các chương sau.

More on Loading Data

Trong thực tế chúng ta thường load data một cách trực tiếp vào Spark Environment. Ví dụ với bộ data mtcars ở định dạng .csv đã được load ở trên:

load_data_to_spark <- spark_read_csv(sc, "cars.csv")

Xem dữ liệu đã load:

head(load_data_to_spark)
## # Source: spark<?> [?? x 11]
##     mpg   cyl  disp    hp  drat    wt  qsec    vs    am  gear  carb
##   <dbl> <int> <dbl> <int> <dbl> <dbl> <dbl> <int> <int> <int> <int>
## 1  21       6   160   110  3.9   2.62  16.5     0     1     4     4
## 2  21       6   160   110  3.9   2.88  17.0     0     1     4     4
## 3  22.8     4   108    93  3.85  2.32  18.6     1     1     4     1
## 4  21.4     6   258   110  3.08  3.22  19.4     1     0     3     1
## 5  18.7     8   360   175  3.15  3.44  17.0     0     0     3     2
## 6  18.1     6   225   105  2.76  3.46  20.2     1     0     3     1

Disconnecting

Sau khi xong mọi công việc chúng ta có thể kết thúc kết nối với local cluster như sau:

spark_disconnect(sc)

Nếu sử dụng nhiều culuster thì:

spark_disconnect(sc)
LS0tDQp0aXRsZTogJ01hc3RlcmluZyBBcGFjaGUgU3Bhcmsgd2l0aCBSIChDaGFwdGVyIDIpJw0KYXV0aG9yOiAnQXV0aG9yOiBOZ3V5ZW4gQ2hpIER1bmcnDQpzdWJ0aXRsZTogIlIgTWFjaGluZSBMZWFybmluZyBTZXJpZXMiDQpvdXRwdXQ6DQogIGh0bWxfZG9jdW1lbnQ6IA0KICAgIGNvZGVfZG93bmxvYWQ6IHRydWUNCiAgICAjIGNvZGVfZm9sZGluZzogaGlkZQ0KICAgIGhpZ2hsaWdodDogemVuYnVybg0KICAgICMgbnVtYmVyX3NlY3Rpb25zOiB5ZXMNCiAgICB0aGVtZTogImZsYXRseSINCiAgICB0b2M6IFRSVUUNCiAgICB0b2NfZmxvYXQ6IFRSVUUNCi0tLQ0KDQpgYGB7ciBzZXR1cCxpbmNsdWRlPUZBTFNFfQ0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KGVjaG8gPSBUUlVFLCB3YXJuaW5nID0gRkFMU0UsIG1lc3NhZ2UgPSBGQUxTRSwgY2FjaGUgPSBUUlVFKQ0KDQpgYGANCg0KIVtdKEM6L1VzZXJzL0FETUlOL0RvY3VtZW50cy9wMS5qcGcpDQoNCiMgUHJlcmVxdWlzaXRlcw0KDQrEkOG7gyBz4butIGThu6VuZyDEkcaw4bujYyBBcGFjaGUgU3BhcmsgY+G6p24gY8OgaSDEkeG6t3Q6IA0KDQoxLiBDw6BpIMSR4bq3dCBbSmF2YSBKREtdKGh0dHBzOi8vd3d3Lm9yYWNsZS5jb20vamF2YS90ZWNobm9sb2dpZXMvamF2YXNlL2phdmFzZS1qZGs4LWRvd25sb2Fkcy5odG1sKS4gDQoyLiBbUl0oaHR0cHM6Ly9jcmFuLnItcHJvamVjdC5vcmcvYmluL3dpbmRvd3MvYmFzZS8pICsgW1IgU3R1ZGlvXShodHRwczovL3d3dy5yc3R1ZGlvLmNvbS9wcm9kdWN0cy9yc3R1ZGlvL2Rvd25sb2FkLykuIA0KMy4gVGjGsCB2aeG7h24gc3BhcmtseXIuIA0KDQpTYXUga2hpIGPDoGkgxJHhurd0IHhvbmcga2nhu4NtIHRyYSBt4buZdCBz4buRIHRow7RuZyB0aW4gduG7gSBwaGnDqm4gYuG6o246DQoNCmBgYHtyfQ0KbGlicmFyeShzcGFya2x5cikNCnNwYXJrX2luc3RhbGxlZF92ZXJzaW9ucygpDQpgYGANCg0KTmjGsCB24bqteSBTcGFyayAoVmVyc2lvbiAyLjQuMykgdsOgIEhhZG9vcCAoVmVyc2lvbiAyLjcpIGPFqW5nIMSRxrDhu6NjIGluc3RhbGwgdHLDqm4gbG9jYWwgbWFjaGluZS4gDQoNCiMgQ29ubmVjdGluZw0KDQpHaeG6oyBz4butIHLhurFuZyB2aeG7h2MgY8OgaSDEkeG6t3QgdsOgIHRoaeG6v3QgbOG6rXAgbcO0aSB0csaw4budbmcgxJHhu4Mgc+G7rSBk4bulbmcgQXBhY2hlIFNwYXJrIChn4buNaSB04bqvdCBsw6AgU3BhcmspIMSRw6MgxJHGsOG7o2MgaG/DoG4gdGjDoG5oLiBDw6FjIGNoxrDGoW5nIHNhdSBz4bq9IGdp4bqjaSB0aMOtY2ggdmnhu4djIHTDrG0sIGPDoGkgxJHhurd0IHbDoCBr4bq/dCBu4buRaSBuaGnhu4F1IFNwYXJrIENsdXN0ZXIgdHLDqm4gbmhp4buBdSBtw6F5IHTDrW5oIGtow6FjIG5oYXUuIFbhu5tpIG3hu6VjIMSRw61uaCBtaW5oIGjhu41hLCBjaMawxqFuZyBuw6B5IHThuq1wIHRydW5nIHbDoG8gduG6rW4gaMOgbmggY29kZSB0csOqbiBsb2NhbCBjbHVzdGVyIChtw6F5IHTDrW5oIGPDoSBuaMOibikuDQoNCg0KxJDhu4Mga+G6v3QgbuG7kWkgduG7m2kgbG9jYWwgY2x1c3RlciB0csOqbiBtw6F5IHTDrW5oIGPDoSBuaMOibiB0aOG7sWMgaGnhu4duIFIgY29kZXMgZMaw4bubaSDEkcOieTogDQoNCmBgYHtyfQ0Kc2MgPC0gc3BhcmtfY29ubmVjdChtYXN0ZXIgPSAibG9jYWwiLCB2ZXJzaW9uID0gIjIuNC4zIikNCmBgYA0KDQpDaMO6bmcgdGEgY8OzIHRo4buDIHhlbSB0aMOqbSBt4buZdCBz4buRIHRow7RuZyB0aW4ga2jDoWMgduG7gSBsb2NhbCBjbHVzdGVyIGLhurFuZyBs4buHbmggc2F1OiANCg0KYGBge3IsIGV2YWw9RkFMU0V9DQpzYw0KYGBgDQoNCg0KIyBT4butIGThu6VuZyBBcGFjaGUgU3BhcmsNCg0KU2F1IGtoaSBr4bq/dCBu4buRaSB24bubaSBsb2NhbCBjbHVzdGVyIGNow7puZyB0YSBz4butIGThu6VuZyBi4buZIGThu68gbGnhu4d1ICoqbXRjYXJzKiogKGPDsyBzxINuIHRyb25nIFIgRW52aXJvbm1lbnQpIMSR4buDIG1pbmggaOG7jWEuIFRyxrDhu5tjIGjhur90IHhlbSBxdWEgYuG7mSBk4buvIGxp4buHdSBuw6B5OiANCg0KYGBge3J9DQpoZWFkKG10Y2FycykNCmBgYA0KDQpMxrB1IGzhuqFpIGLhu5kgZOG7ryBsaeG7h3UgbsOgeSDhu58gxJHhu4tuaCBk4bqhbmcgLmNzdiDEkeG7gyBz4butIGThu6VuZyBzYXUgbsOgeSBu4bq/dSBj4bqnbiB0aGnhur90OiANCg0KYGBge3J9DQp3cml0ZS5jc3YobXRjYXJzLCAiY2Fycy5jc3YiLCByb3cubmFtZXMgPSBGQUxTRSkNCmBgYA0KDQpT4butIGThu6VuZyBs4buHbmggYGNvcHlfdG8oKWAgxJHhu4MgY29weSBi4buZIGThu68gbGnhu4d1IG10Y2FycyB04burIG3DtGkgdHLGsOG7nW5nIFIgdsOgbyBBcGFjaGUgU3Bhcms6IA0KDQpgYGB7cn0NCmNhcnMgPC0gY29weV90byhzYywgbXRjYXJzKQ0KYGBgDQoNCkNow7puZyB0YSBjw7MgdGjhu4MgYWNjZXNzIGLhu5kgZOG7ryBsaeG7h3UgbsOgeSB0aMO0bmcgcXVhIFIuIFbDrSBk4bulOiANCg0KYGBge3J9DQpoZWFkKGNhcnMpDQpgYGANCg0KIyBXZWIgSW50ZXJmYWNlDQoNCkjhuqd1IGjhur90IFNwYXJrIGNvbW1hbmRzIMSRxrDhu6NjIHRo4buxYyBoaeG7h24gdOG7qyBSc3R1ZGlvL1IgY29uc29sZS4gVHV5IG5oacOqbiB2aeG7h2MgdGhlbyBkw7VpICh2w6AgY8OhYyBxdcOhIHRyw6xuaCBraMOhYykgxJHGsOG7o2MgdGjhu7FjIGhp4buHbiB0aMO0bmcgcXVhIGdpYW8gZGnhu4duIFdlYiBj4bunYSBTcGFyay4gR2lhbyBkaeG7h24gIG7DoHkgbMOgIG3DtHQgd2ViIGFwcGxpY2F0aW9uIMSRxrDhu6NjIGN1bmcgY+G6pXAgYuG7n2kgU3BhcmsgYuG6sW5nIGPDoWNoIHRo4buxYyBoaeG7h24gbOG7h25oIHNhdTogDQoNCg0KYGBge3J9DQpzcGFya193ZWIoc2MpDQpgYGANCg0KS+G6v3QgcXXhuqMgc+G6vSBuaMawIGTGsOG7m2kgxJHDonk6IA0KDQohW10oQzovVXNlcnMvQURNSU4vRG9jdW1lbnRzL3AzLnBuZykNCiMgRGF0YSBRdWVyeSBhbmQgTWFuaXB1bGF0aW9uDQoNCktoaSBz4butIGThu6VuZyBTcGFyayB0aMO0bmcgcXVhIFIgY2jDum5nIHRhIGPDsyB0aOG7gyBz4butIGThu6VuZyBjw6FjIG5nw7RuIG5n4buvIHRydXkgduG6pW4gZOG7ryBsaeG7h3UuIENo4bqzbmcgaOG6oW4gc+G7rSBk4bulbmcgU1FMIMSR4buDIMSR4bq/bSBz4buRIGTDsm5nOiANCg0KYGBge3J9DQpsaWJyYXJ5KERCSSkNCmRiR2V0UXVlcnkoc2MsICJTRUxFQ1QgY291bnQoKikgRlJPTSBtdGNhcnMiKQ0KYGBgDQoNCkhv4bq3YyBz4butIGThu6VuZyBjw6FjIGjDoG0gY+G7p2EgdGjGsCB2aeG7h24gKipkcGx5cioqOiANCg0KYGBge3J9DQpsaWJyYXJ5KGRwbHlyKQ0KDQpjYXJzICU+JSANCiAgZ3JvdXBfYnkoY3lsKSAlPiUgDQogIGNvdW50KHNvcnQgPSBUUlVFKQ0KYGBgDQoNCiMgTW9kZWxsaW5nDQoNClNhdSBraGkgbG9hZCBi4buZIGThu68gbGnhu4d1IG10Y2FycyB2w6BvIFNwYXJrIEVudmlyb25tZW50IGNow7puZyB0YSBjw7MgdGjhu4MsIHbDrSBk4bulLCDEkcOhbmggZ2nDoSB0w6FjIMSR4buZbmcgY+G7p2EgaG9yc2Vwb3dlciBsw6puIGZ1ZWwgZWZmaWNpZW5jeSB0aMO0bmcgcXVhIGjhu5NpIHF1eTogDQoNCmBgYHtyfQ0KbW9kZWwgPC0gbWxfbGluZWFyX3JlZ3Jlc3Npb24oY2FycywgbXBnIH4gaHApDQpgYGANCg0KVuG7m2kgbcO0IGjDrG5oIMSRw6MgaHXhuqVuIGx1eeG7h24geG9uZyBjaMO6bmcgdGEgY8OzIHRo4buDIHPhu60gZOG7pW5nIG3DtCBow6xuaCBuw6B5IMSR4buDIGThu7EgYsOhbyBt4bupYyDEkeG7mSBmdWVsIGVmZmljaWVuY3kgY+G7p2EsIHbDrSBk4bulLCBiYSBxdWFuIHPDoXQgduG7m2kgaG9yc2Vwb3dlciBs4bqnbiBsxrDhu6N0IGzDoCAyNTAsIDI2MCB2w6AgMjcwIG5oxrAgc2F1OiANCg0KYGBge3J9DQojIFNvbWUgZGF0YSBwb2ludHM6IA0KbXlfZGYgPC0gZGF0YS5mcmFtZShocCA9IGMoMjUwLCAyNjAsIDI3MCkpDQoNCiMgTG9hZCB0byBTcGFyayBlbnZpcm9ubWVudDogDQpteV9kZl9zcGFyayA8LSBjb3B5X3RvKHNjLCBteV9kZikNCg0KIyBVc2UgdHJhaW5lZCBtb2RlbCBmb3IgcHJlZGljdGluZzogDQptbF9wcmVkaWN0KG1vZGVsLCBteV9kZl9zcGFyaykgLT4gbXBnX3ByZWRpY3RlZA0KDQojIFNob3cgcmVzdWx0czogDQptcGdfcHJlZGljdGVkIA0KYGBgDQoNCk9LLiBDaMO6YyBt4burbmcgYuG6oW4uIELhuqFuIHbhu6thIHPhu60gZOG7pW5nIG3DtCBow6xuaCB0cmFpbiDEkcaw4bujYyBi4bqxbmcgU3BhcmsgxJHhu4MgxJHGsGEgcmEgY8OhYyBnacOhIHRy4buLIGThu7EgYsOhbyBs4bqnbiBsxrDhu6N0IGzDoCAxMy4wLCAxMi40IHbDoCAxMS43LiBUaOG7sWMgdOG6vyB0aMOsIHZp4buHYyBodeG6pW4gbHV54buHbiBjw6FjIG3DtCBow6xuaCBo4buNYyBtw6F5IHPhur0gY8OybiBuaGnhu4F1IGLGsOG7m2MgdsOgIGPDtG5nIMSRb+G6oW4gaMahbiB0b3kgZXhhbXBsZSB24burYSB0csOsbmggYsOgeSDhu58gdHLDqm4uIE5o4buvbmcgxJFp4buBdSBuw6B5IHPhur0gxJHGsOG7o2MgdHLDrG5oIGLDoHkgdHJvbmcgY8OhYyBjaMawxqFuZyBzYXUuIA0KDQojIE1vcmUgb24gTG9hZGluZyBEYXRhDQoNClRyb25nIHRo4buxYyB04bq/IGNow7puZyB0YSB0aMaw4budbmcgbG9hZCBkYXRhIG3hu5l0IGPDoWNoIHRy4buxYyB0aeG6v3AgdsOgbyBTcGFyayBFbnZpcm9ubWVudC4gVsOtIGThu6UgduG7m2kgYuG7mSBkYXRhIG10Y2FycyDhu58gxJHhu4tuaCBk4bqhbmcgLmNzdiDEkcOjIMSRxrDhu6NjIGxvYWQg4bufIHRyw6puOiANCg0KYGBge3J9DQpsb2FkX2RhdGFfdG9fc3BhcmsgPC0gc3BhcmtfcmVhZF9jc3Yoc2MsICJjYXJzLmNzdiIpDQpgYGANCg0KWGVtIGThu68gbGnhu4d1IMSRw6MgbG9hZDogDQoNCmBgYHtyfQ0KaGVhZChsb2FkX2RhdGFfdG9fc3BhcmspDQpgYGANCg0KIyBEaXNjb25uZWN0aW5nDQoNClNhdSBraGkgeG9uZyBt4buNaSBjw7RuZyB2aeG7h2MgY2jDum5nIHRhIGPDsyB0aOG7gyBr4bq/dCB0aMO6YyBr4bq/dCBu4buRaSB24bubaSBsb2NhbCBjbHVzdGVyIG5oxrAgc2F1OiANCg0KYGBge3J9DQpzcGFya19kaXNjb25uZWN0KHNjKQ0KYGBgDQoNCk7hur91IHPhu60gZOG7pW5nIG5oaeG7gXUgY3VsdXN0ZXIgdGjDrDogDQoNCmBgYHtyfQ0Kc3BhcmtfZGlzY29ubmVjdChzYykNCmBgYA0KDQoNCg0KDQoNCg0KDQoNCg==