Thuc Hanh Data Mining R

35
1/35 Bài ging thc hành KHAI KHOÁNG DLIU Biên son : Phm Nguyên Khang Mc lc 1. R căn bản 2 1.1. Tải và cài đặt R 2 2. Các phép toán cơ bản trên R 6 2.1. Sử dụng R như máy tính điện tử bỏ túi 6 2.2. Véctơ 7 2.3. Ma trận 9 2.4. Vẽ đồ thị 12 2.5. Khung dữ liệu (Data frame) 15 2.6. Tạo/Thay đổi dữ liệu 18 2.7. Trợ giúp 19 3. R cho data mining 20 3.1. Đọc khung dữ liệu từ file 20 3.2. Xây dựng mô hình dự báo 22 3.3. Kho dữ liệu cho Data mining và Học máy 23 3.4. Giải thuật k láng giềng (kNN) 24 3.5. Cây quyết định 29 3.6. Bayes ngây thơ (Naïve Bayes) 32

description

Thực hành lập trình R

Transcript of Thuc Hanh Data Mining R

1/35

Bài giảng thực hành KHAI KHOÁNG DỮ LIỆU

Biên soạn : Phạm Nguyên Khang

Mục lục

1.   R  căn  bản   2  1.1.   Tải  và  cài  đặt  R   2  

2.   Các  phép  toán  cơ  bản  trên  R   6  2.1.   Sử  dụng  R  như  máy  tính  điện  tử  bỏ  túi   6  2.2.   Véc-­‐tơ   7  2.3.   Ma  trận   9  2.4.   Vẽ  đồ  thị   12  2.5.   Khung  dữ  liệu  (Data  frame)   15  2.6.   Tạo/Thay  đổi  dữ  liệu   18  2.7.   Trợ  giúp   19  

3.   R  cho  data  mining   20  3.1.   Đọc  khung  dữ  liệu  từ  file   20  3.2.   Xây  dựng  mô  hình  dự  báo   22  3.3.   Kho  dữ  liệu  cho  Data  mining  và  Học  máy   23  3.4.   Giải  thuật  k  láng  giềng  (k-­‐NN)   24  3.5.   Cây  quyết  định   29  3.6.   Bayes  ngây  thơ  (Naïve  Bayes)   32  

2/35

BUỔI 1. R CĂN BẢN

Mục tiêu:

• Biết cách cài đặt R và các gói bổ sung • Biết sử dụng R để thực hiện các phép toán số học, véc-tơ, ma trận • Hiểu nguyên lý hoạt động của ngôn ngữ R: lệnh, hàm, scritps • Biết cách vẽ đồ thị trên R • Sử dụng được các kiểu dữ liệu cơ bản trong R: số, chuỗi, luận lý, véc-tơ, list, khung dữ liệu.

1. R căn bản 1.1. Tải và cài đặt R

1.1.1. Cài đặt R

Vào trang web (http://www.r-project.org) để download và cài đặt

1.1.2. Cài đặt bổ sung các gói cho R

a. Cài trực tiếp từ internet (Nếu máy tính có kết nối internet) Từ menu chọn Packages/Install package(s)… Chọn mirror từ danh sách bên dưới. Click Ok.

3/35

Chọn gói cần cài đặt, click Ok

b. Cài cục bộ từ file

Download các gói từ internet trước. Để tìm kiếm 1 gói nào đó trong R có thể dùng Google. Ví dụ: tìm gói “tree”

4/35

Click link đầu tiên để xem gói này.

Chọn phiên bản phù hợp với hệ điều hành đang dùng (ví dụ: Windows binary).

Lưu file tree_1.0-34.zip vào thư mục nào đó (ví dụ: C:\R-packages)

Giả sử bạn đã download hoặc copy các file zip vào thư mục C:\R-packages.

Click phải trên My Computer đặt thêm biến môi trường R_LIBS chỉ đến thư mục chứa các file zip.

5/35

Để kiểm tra xem biến này có tác dụng chưa, mở R gõ lệnh .libPaths(). Nếu kết quả như hình bên dưới là Ok.

6/35

Để cài đặt, vào menu, chọn Packages/Install package(s) from local zip files…

Chọn file zip

2. Các phép toán cơ bản trên R

2.1. Sử dụng R như máy tính điện tử bỏ túi Ví dụ:

> 2 + 3 * 5 # Chú ý thứ tự các phép toán. > log (10) # Logaric cơ số e=2.718282 > 4^2 # 4 lũy thừa 2 > 3/2 # 3 chia 2 > sqrt (16) # Căn bậc 2 của 16 > abs (3-7) # giá trị tuyệt đối của 3 trừ 7 > pi # Số pi > exp(2) # e lũy thừa 2 > 15 %/% 4 # Phép chia lấy phần nguyên > # Đây là dòng chú thích

Phép gán (<-).

Chú ý: R phân biệt chữ hoa, chữ thường

> x<- log(2.843432) *pi > x [1] 3.283001 > sqrt(x) [1] 1.811905 > floor(x) # số nguyên lớn nhất <= x [1] 3

7/35

> ceiling(x) # số nguyên nhỏ nhất >= x [1] 4

R có thể xử lý được cả số phức. > x<-3+2i > Re(x) # phần thực của số phức x [1] 3 > Im(x) # phần ảo của số phức x [1] 2 > y<- -1+1i > x+y [1] 2+3i > x*y [1] -5+1i

Chú ý quan trọng: vì có khá nhiều hàm có sẵn trong R, nên khi đặt tên biến hãy cẩn thận lựa chọn tên biến tránh trùng lặp với các từ khóa. Ví dụ c, pi, …Đừng bao giờ đặt tên biến là c.

2.2. Véc-tơ

R xử lý các phép toán trên véc-tơ rất dễ dàng và trực quan.

> x<-c(1,3,2,10,5) #tạo vector x có 5 phần tử > x [1] 1 3 2 10 5 > y<-1:5 #tạo vector các phần tử từ 1 đến 5 > y [1] 1 2 3 4 5 > y+2 #cộng các phần tử của y với 2 [1] 3 4 5 6 7 > 2*y #nhân các phần tử của y với 2 [1] 2 4 6 8 10 > y^2 #bình phương các phần tử của y [1] 1 4 9 16 25 > 2^y #lấy 2 lũy thừa theo từng phần tử của y [1] 2 4 8 16 32 > y #hiển thị y [1] 1 2 3 4 5 > y<-y*2 #gán y bằng y*2 > y #các phần tử của y giờ đã thay đổi [1] 2 4 6 8 10

Một số ví dụ nữa: > x<-c(1,3,2,10,5); y<-1:5 #viết 2 lệnh trên cùng 1 dòng, phải dùng dấu chấm phẩy để ngăn cách > x+y #cộng 2 véc-tơ [1] 2 5 5 14 10 > x*y #lấy các phần tử của 2 véc-tơ nhân với nhau [1] 1 6 6 40 25 > x/y [1] 1.0000000 1.5000000 0.6666667 2.5000000 1.0000000

8/35

> x^y [1] 1 9 8 10000 3125

> sum(x) #tổng các phần tử của x [1] 21 > cumsum(x) #tạo véc-tơ mới từ x bằng cách cộng dồn [1] 1 4 6 16 21 > diff(x) #Lấy số sau trừ số trước (cách nhau 1 số) [1] 2 -1 8 -5 > diff(x,2) #Lấy số sau trừ số trước (cách nhau 2 số) [1] 1 7 3 > max(x) #Tìm số lớn nhất [1] 10 > min(x) #Tìm số bé nhất [1] 1

Sắp xếp: dùng hàm sort() > x [1] 1 3 2 10 5 > sort(x) # sắp xếp tăng dần [1] 1 2 3 5 10 > sort(x, decreasing=T) # sắp xếp giảm dần [1] 10 5 3 2 1

Truy xuất các phần tử của véc-tơ > x [1] 1 3 2 10 5 > length(x) # đếm số phần tử của x [1] 5 > x[3] # phần tử thứ 3 của x [1] 2 > x[3:5] # lấy các phần tử từ 3 đến 5 [1] 2 10 5 > x[-2] # lấy hết trừ phần tử thứ 2 [1] 1 2 10 5 > x[x>3] # lấy các phần tử lớn hơn 3 [1] 10 5

Xử lý véc-tơ có kiểu TRUE/FALSE: > x>3 [1] FALSE FALSE FALSE TRUE TRUE > as.numeric(x>3) # hàm as.numeric() ép kiểu TRUE/FALSE thành 1/0 [1] 0 0 0 1 1 > sum(x>3) # Số các phần tử lớn hơn 3 [1] 2 > (1:length(x))[x<=2] # Chỉ số của các phần tử <= 2 [1] 1 3 > z<-as.logical(c(1,0,0,1)) # ép kiểu số (1/0) thành logic (TRUE/FALSE) > z [1] TRUE FALSE FALSE TRUE

9/35

Véc-tơ chuỗi ký tự: > colors<-c("green", "blue", "orange", "yellow", "red") > colors [1] "green" "blue" "orange" "yellow" "red"

Có thể đặt tên cho các phần tử của véc-tơ để dễ truy xuất. > names(x) # kiểm tra xem x có đặt tên cho các phần tử chưa NULL # chưa đặt tên > names(x)<-colors # đặt tên cho các phần tử x là các phần tử trong colors > names(x) [1] "green" "blue" "orange" "yellow" "red" > x green blue orange yellow red 1 3 2 10 5 > x["green"] # truy xuất phần tử thông qua tên đã đặt 1 > names(x)<-NULL # xóa hết các tên đã đặt > x [1] 1 3 2 10 5

Hàm seq() và rep() dùng để tạo các véc-tơ đặc biệt: > seq(10) # tạo các phần tử từ 1 đến 10 [1] 1 2 3 4 5 6 7 8 9 10 > seq(0,1,length=10) # tạo 10 phần tử từ 0 đến 1, cách đều nhau [1] 0.0000000 0.1111111 0.2222222 0.3333333 0.4444444 0.5555556 0.6666667 [8] 0.7777778 0.8888889 1.0000000 > seq(0,1,by=0.1) # tạo các phần tử từ 0 đến 1, cách nhau 0.1 [1] 0.0 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1.0 > rep(1,3) # lặp lại số 1 ba lần [1] 1 1 1 > c(rep(1,3),rep(2,2),rep(-1,4)) # lặp lại số 1 ba lần, số 2 hai lần, số -1 bốn lần [1] 1 1 1 2 2 -1 -1 -1 -1 > rep("Small",3) # lặp lại chuỗi Small ba lần [1] "Small" "Small" "Small" > c(rep("Small",3),rep("Medium",4)) # lặp lại chuỗi Small 3 lần, chuỗi Medium 4 lần [1] "Small" "Small" "Small" "Medium" "Medium" "Medium" "Medium" > rep(c("Low","High"),3) # lặp lại véc-tơ Low High ba lần [1] "Low" "High" "Low" "High" "Low" "High"

2.3. Ma trận

Ma trận là một mảng 2 chiều có m hàng và n cột. Cách dễ nhất để tạo ma trận là ghép các véc-tơ có chiều dài như nhau dùng hàm cbind(), có nghĩa là ghép theo cột (column bind): > x [1] 1 3 2 10 5

10/35

> y [1] 1 2 3 4 5 > m1<-cbind(x,y);m1 #tạo ma trận m1 bằng cách ghép hai véc-tơ x và y x y [1,] 1 1 [2,] 3 2 [3,] 2 3 [4,] 10 4 [5,] 5 5 > t(m1) # ma trận chuyển vị của m1 [,1] [,2] [,3] [,4] [,5] x 1 3 2 10 5 y 1 2 3 4 5

> m1<-t(cbind(x,y)) # ta cũng có thể ghép xong rồi tính chuyển vị luôn > dim(m1) # trả về kích thước của ma trận (cột x hàng) [1] 2 5 > m1<-rbind(x,y) # rbind() tương tự cbind() nhưng ghép theo hàng.

Ta cũng có thể tạo ma trận bằng cách liệt kê các phần tử của nó: > m2<-matrix(c(1,3,2,5,-1,2,2,3,9),nrow=3);m2 # tạo ma trân m2 gồm 9 phần tử, có 3 hàng, các phần tử được liệt kê theo từng cột [,1] [,2] [,3] [1,] 1 5 2 [2,] 3 -1 3 [3,] 2 2 9

Chú ý: mặc định R hiểu là ta đang liệt kê theo từng cột. Nếu muốn liệt kê theo từn hàng, ta chỉ định byrow=T > m2<-matrix(c(1,3,2,5,-1,2,2,3,9),ncol=3,byrow=T);m2 [,1] [,2] [,3] [1,] 1 3 2 [2,] 5 -1 2 [3,] 2 3 9

Xem nội dung ma trận: gõ tên biến tương ứng > m2 [,1] [,2] [,3] [1,] 1 3 2 [2,] 5 -1 2 [3,] 2 3 9 > m2[2,3] # truy xuất phần tử hàng 2 cột 3 [1] 2 > m2[2,] # toàn bộ hàng 2 [1] 5 -1 2 > m2[,3] # toàn bộ cột 3 [1] 2 2 9 > m2[-1,] # ma trận con thu được bằng cách lấy hết trừ hàng 1 [,1] [,2] [,3]

11/35

[1,] 5 -1 2 [2,] 2 3 9 > m2[,-1] # tương tự, lấy hết trừ cột 1 [,1] [,2] [1,] 3 2 [2,] -1 2 [3,] 3 9 > m2[-1,-1] # lấy hết, trừ hàng 1 và cột 1 [,1] [,2] [1,] -1 2 [2,] 3 9

Các phép toán trên ma trận có thể được thực hiện khá dễ dàng. > m1<-matrix(1:4, ncol=2); m2<-matrix(c(10,20,30,40),ncol=2) > 2*m1 # nhân các phần tử của ma trận với 2 [,1] [,2] [1,] 2 6 [2,] 4 8 > m1+m2 # cộng hai ma trận [,1] [,2] [1,] 11 33 [2,] 22 44 > m1*m2 # nhân từng phần tử tương ứng của 2 ma trận với nhau [,1] [,2] [1,] 10 90 [2,] 40 160

Chú ý là m1*m2 KHÔNG phải là phép nhân ma trận thông thường. Nếu muốn nhân 2 ma trận theo kiểu thông thường, sử dụng phép toán %*%

> m1 %*% m2 [,1] [,2] [1,] 70 150 [2,] 100 220

> solve(m1) # tính ma trận nghich đảo của ma trận m1 [,1] [,2] [1,] -2 1.5 [2,] 1 -0.5 > solve(m1)%*%m1 # kiểm tra lại xem có đúng là ma trận nghịch đảo không, nếu đúng tích của chúng phải là ma trận đơn vị [,1] [,2] [1,] 1 0 [2,] 0 1 > diag(3) #diag() xây dựng ma trận đơn vị 3 x 3 [,1] [,2] [,3] [1,] 1 0 0 [2,] 0 1 0 [3,] 0 0 1 > diag(c(2,3,3)) # xây dựng ma trận đường chéo [,1] [,2] [,3] [1,] 2 0 0

12/35

[2,] 0 3 0 [3,] 0 0 3

Tính giá trị riêng và véc-tơ riêng: hàm eigen() > eigen(m2) $values # giá trị riêng của m2 [1] 53.722813 -3.722813

$vectors # các véc-tơ riêng tương ứng [,1] [,2] [1,] -0.5657675 -0.9093767 [2,] -0.8245648 0.4159736

2.4. Danh sách (list)

Kiểu danh sách tương tự như kiểu véc-tơ ngoại trừ việc list cho phép các phần tử trong danh sách có kiểu khác nhau.

Ví dụ:

> list(2, "a", TRUE) [[1]] [1] 2 [[2]] [1] "a" [[3]] [1] TRUE

Ta có danh sách gồm 3 phần tử có kiểu lần lượt là: số, chuỗi và luận lý. Để truy xuất phần tử thứ I trong danh sách ta sử dụng toán tử [[i]] , ví dụ:

> d<- list(2, "a", TRUE) > d[[1]] [1] 2 > d[[2]] [1] "a" > d[[3]] [1] TRUE Ta cũng có thể tận dụng tính năng cách đặt tên cho các phần tử trong một danh sách để sử dụng list như kiểu đối tượng để lưu dữ liệu có cấu trúc bất kỳ kiểu <tên-trường> <giá-trị> như kiểu struct trong C hay kiểu record trong PASCAL. Ví dụ: ta tạo một đối tượng node gồm có nhãn (label) có giá trị ‘pos’, con trái (left) và con phải (right) có giá trị rỗng. node <- list(label=’pos’, left=list(), right=list()) Để truy xuất trường label của node ta sử dụng : > node[['label']] [1] "pos" Ta cũng có thể gán trường right của node chỉ vào 1 nút khác :

13/35

> node[['right']] <- list(label='neg', left=list(), right=list()) > node $label [1] "pos" $left list() $right $right$label [1] "neg" $right$left list() $right$right list() Bằng cách này ta có thể lưu trữ bất kỳ kiểu dữ liệu có cấu trúc như thế nào. 2.5. Vẽ đồ thị

R cung cấp công cụ vẽ đồ thị hàm số khá mạnh. Ví dụ bên dưới định nghĩa hàm

3

)(log2 xxexy −−= và vẽ đồ thị hàm số này bằng hàm plot().

y.fun <- function (x) # định nghĩa hàm y = f(x) { (log(x))^2-x*exp(-x^3) } x <- seq(0.2, 2, 0.01) # tạo dãy các giá trị x từ 0.2 đến 2, cách nhau 0.01 y <- y.fun(x) # gán y = f(x) win.graph() # khởi tạo đồ thị plot(x,y,type="l") # vẽ đồ thị với 2 véc-tơ x, y, kiểu line. abline(h=0) # vẽ đường ngang y = 0

14/35

Hàm trong R được định nghĩa bằng cú pháp:

Ví dụ bên dưới định nghĩa hàm add có hai đối số a, b trả về tổng của chúng.

Mặc định, kết quả của lệnh cuối cùng cũng sẽ là kết quả trả về của hàm. Nếu muốn trả về trước lệnh cuối cùng (trong trường hợp sử dụng các lệnh rẽ nhánh, vòng lặp) ta sử dụng hàm return, ví dụ:

R cũng hỗ trợ đệ quy. Ví sau đây định nghĩa hàm giai_thua tính giai thừa của một số nguyên.

tênhàm <- function(thamso1, thamso2, thamso3, …) { thân hàm kết quả trả về }

add <- function(a, b) { a + b }

add <- function(a, b) { return(a + b) }

15/35

2.6. Khung dữ liệu (Data frame)

Ta có thể xem khung dữ liệu như một danh sách các cột, mỗi cột có thể có một kiểu dữ liệu khác nhau (số: numeric, ký tự: character, v.v.). Đây là đối tượng quan trọng nhất mà ta thường dùng để xử lý số liệu. Có thể xem khung dữ liệu chính là bảng dữ liệu đầu vào của giai đoạn Khai phá dữ liệu trong quy trình KDD của chúng ta (xem lại lý thuyết về quy trình KDD).

Dữ liệu kích thước nhỏ hoặc trung bình có thể tạo bằng hàm data.frame(). Ví dụ sau đây minh họa việc tạo khung dữ liệu cho bộ dữ liệu xe hơi: Mỗi hàng là 1 chiếc xe, mỗi cột tương ứng là các thuộc tính của nó: hang sản xuất (Make), Model, Xi-lanh (Cylinder), Khối lượng (Weigth), Số dặm/km đã sử dụng (Mileage), Kiểu (Type)

Make Model Cylinder Weight Mileage Type Honda Civic V4 2170 33 Sporty Chevrolet Beretta V4 2655 26 Compact Ford Escort V4 2345 33 Small Eagle Summit V4 2560 33 Small Volkswagen Jetta V4 2330 26 Small Buick Le Sabre V6 3325 23 Large Mitsubishi Galant V4 2745 25 Compact Dodge Grand Caravan V6 3735 18 Van Chrysler New Yorker V6 3450 22 Medium Acura Legend V6 3265 20 Medium

Đầu tiên tạo dữ liệu cho từng cột

> Make <-c("Honda","Chevrolet","Ford","Eagle","Volkswagen","Buick","Mitsbusihi", "Dodge","Chrysler","Acura") > Model<-c("Civic","Beretta","Escort","Summit","Jetta","Le Sabre","Galant", "Grand Caravan","New Yorker","Legend")

Có thể sử dụng hàm rep() để lặp lại 1 số giá trị giống nhau ví dụ: rep("V4",5) sẽ lặp lại V4 năm lần.

giai_thua <- function(n) { if (n == 0) return(1) giai_thua(n - 1) * n } Khi gọi 4! sẽ cho kết quả 24. > giai_thua(4) [1] 24

16/35

> Cylinder<-c(rep("V4",5),"V6","V4",rep("V6",3)) > Cylinder [1] "V4" "V4" "V4" "V4" "V4" "V6" "V4" "V6" "V6" "V6" > Weight<-c(2170,2655,2345,2560,2330,3325,2745,3735,3450,3265) > Mileage<-c(33,26,33,33,26,23,25,18,22,20) > Type<-c("Sporty","Compact",rep("Small",3),"Large","Compact","Van",rep("Medium",2))

Bây giờ, sử dụng hàm data.frame() ghép các cột lại với nhau tạo thành KHUNG DỮ LIỆU. > Car<-data.frame(Make,Model,Cylinder,Weight,Mileage,Type) > Car Make Model Cylinder Weight Mileage Type 1 Honda Civic V4 2170 33 Sporty 2 Chevrolet Beretta V4 2655 26 Compact 3 Ford Escort V4 2345 33 Small 4 Eagle Summit V4 2560 33 Small 5 Volkswagen Jetta V4 2330 26 Small 6 Buick Le Sabre V6 3325 23 Large 7 Mitsbusihi Galant V4 2745 25 Compact 8 Dodge Grand Caravan V6 3735 18 Van 9 Chrysler New Yorker V6 3450 22 Medium 10 Acura Legend V6 3265 20 Medium

> names(Car) [1] "Make" "Model" "Cylinder" "Weight" "Mileage" "Type"

Giống như ma trận, ta có thể truy xuất các phần tử của một Khung dữ liệu bằng cặp dấu ngoặc [], ví dụ: > Car[1,] Make Model Cylinder Weight Mileage Type 1 Honda Civic V4 2170 33 Sporty

Hơn nữa, ta cũng có thể lấy ra từng cột bằng cách sử dụng tên cột: > Car$Mileage [1] 33 26 33 33 26 23 25 18 22 20 > Car[,5] # cho kết quả tương đương > mean(Car$Mileage) # tính trung bình các giá trị trong cột Mileage [1] 25.9 > min(Car$Weight) # tìm giá trị nhỏ nhất trong cột Weight [1] 2170

Hàm table() cho biết tần số xuất hiện từng giá trị trong 1 cột: > table(Car$Type)

Compact Large Medium Small Sporty Van 2 1 2 3 1 1

Trong ví dụ này, table cho ta biết Compact xuất hiện 2 lần trong cột Type, Large xuất hiện 1 lần, …

17/35

Nếu muốn tính tỉ lệ trên 10 chiếc xe, thì ta chia kết quả cho 10: > table(Car$Type)/10

Compact Large Medium Small Sporty Van 0.2 0.1 0.2 0.3 0.1 0.1

Chú ý là ta chia cho 10 là vì biết có 10 chiếc xe trong Khung dữ liệu Car. Nếu không biết ta có đếm số phần tử trong cột Type bằng hàm length(): > table(Car$Type)/length(Car$Type)

Ta cũng có thể tạo bảng tần số đồng xuất hiện của các giá trị có trong hai cột (Cross tabulation): > table(Car$Make, Car$Type)

Compact Large Medium Small Sporty Van Acura 0 0 1 0 0 0 Buick 0 1 0 0 0 0 Chevrolet 1 0 0 0 0 0 Chrysler 0 0 1 0 0 0 Dodge 0 0 0 0 0 1 Eagle 0 0 0 1 0 0 Ford 0 0 0 1 0 0 Honda 0 0 0 0 1 0 Mitsbusihi 1 0 0 0 0 0 Volkswagen 0 0 0 1 0 0

Trong bảng trên, ta thấy rằng có 1 chiếc xe do hang Acura sản xuất và có kiểu là Medium (in đậm, màu đỏ).

Nếu muốn sắp xếp dữ liệu (tăng hoặc giảm) theo 1 cột nào đó, hãy sử dụng hàm order(). Ví dụ sau đây sắp xếp các chiếc xe theo khối lượng tăng dần:

Ta làm điều này bằng 2 bước:

1. Lấy chỉ số của các phần tử (được sắp xếp tăng dần theo trọng lượng):

i <- order(Car$Weight)

2. Đưa các chỉ số này cho Car để in ra các phần tử theo thứ tự trong i.

Car[i,]

18/35

> i<-order(Car$Weight);i [1] 1 5 3 4 2 7 10 6 9 8 > Car[i,] Make Model Cylinder Weight Mileage Type 1 Honda Civic V4 2170 33 Sporty 5 Volkswagen Jetta V4 2330 26 Small 3 Ford Escort V4 2345 33 Small 4 Eagle Summit V4 2560 33 Small 2 Chevrolet Beretta V4 2655 26 Compact 7 Mitsbusihi Galant V4 2745 25 Compact 10 Acura Legend V6 3265 20 Medium 6 Buick Le Sabre V6 3325 23 Large 9 Chrysler New Yorker V6 3450 22 Medium 8 Dodge Grand Caravan V6 3735 18 Van

2.7. Tạo/Thay đổi dữ liệu

> y [1] 1 2 3 4 5

Giả sử véc-tơ y chứa các phần tử từ 1 đến 5. Nếu muốn thay đổi nội dung của y, ta dùng hàm edit() và gán kết quả trở về ngược lại cho y. > y<-edit(y)

Nếu muốn nhập dữ liệu cho khung dữ liệu trực tiếp trên bảng như Excel, gõ > data1<-edit(data.frame())

Sau khi nhập thử vài phần tử, kết quả có thể như thế này:

19/35

Ta có thể thay đổi tên biến bằng cách nhấp vào ô tương ứng và thay đổi nội dung:

Sau khi thay đổi xong, click để đóng lại. Quay trở về cửa sổ lệnh và kiểm tra dữ liệu vừa mới nhập:

> data1

Đối với dữ liệu lớn, ta có thể tạo khung thông qua các hàm đọc dữ liệu: scan, read.table, … 2.8. Trợ giúp Để xem cú pháp và các thông tin có liên quan đến một hàm nào đó trong R ta sử dụng hàm help. Ví dụ:

help(tree) sẽ hiển thị các thông tin có liên quan đến hàm tree dùng để xây dựng cây quyết định.

20/35

BUỔI 2. R CHO KHAI KHOÁNG DỮ LIỆU Mục tiêu:

• Biết cách đọc dữ liệu từ file • Hiểu nguyên lý hoạt động của hàm read.table. • Áp dụng đọc, ghi dữ liệu ra file • Hiểu được mô tả của dữ liệu: số phần tử, số thuộc tính, lớp/nhãn • Sử dụng được giải thuật kNN trong R để thực hiện phân lớp trên 1 số tập dữ liệu từ UCI • Vận dụng lý thuyết về kNN để cài đặt giải thuật kNN.

3. R cho data mining

3.1. Đọc khung dữ liệu từ file

Sử dụng hàm read.table

Mở notepad, soạn thảo file như bên dưới, lưu lại ở đâu đó (ví dụ : D:\car.txt)

Đọc dữ liệu này lên khung dữ liệu a. Kí tự phân cách là dấu chấm phẩy ( ;), dữ liệu này có dòng tiêu đề (sử dụng header=T)

> a <- read.table('d:/car.txt', sep=';', header=T) > a make model mpg weight price 1 AMC Concord 22 2930 4099 2 AMC Pacer 17 3350 4749 3 AMC Spirit 22 2640 3799 4 Buick Century 20 3250 4816 5 Buick Electra 15 4080 7827

Nếu không sử dụng header=T, R sẽ xem dòng đầu tiên cũng là dữ liệu và tự động thêm tiêu đề cho các cột là V1, V2, …

> a <- read.table('d:/car.txt', sep=';') > a V1 V2 V3 V4 V5 1 make model mpg weight price 2 AMC Concord 22 2930 4099 3 AMC Pacer 17 3350 4749 4 AMC Spirit 22 2640 3799 5 Buick Century 20 3250 4816 6 Buick Electra 15 4080 7827

Lấy ngẫu nhiên hai dòng của a

> nrow <- length(a[,1]) # lấy số hàng (dòng) của a > nrow [1] 6

make;model;mpg;weight;price AMC;Concord;22;2930;4099 AMC;Pacer;17;3350;4749 AMC;Spirit;22;2640;3799 Buick;Century;20;3250;4816 Buick;Electra;15;4080;7827

21/35

> idx <- sample(nrow, 2, replace=F) # lấy ra 2 số ngẫu nhiên từ 1 đến nrow > idx [1] 4 6 > a[idx, ] # lấy ra 2 hàng ngẫu nhiên V1 V2 V3 V4 V5 4 AMC Spirit 22 2640 3799 6 Buick Electra 15 4080 7827

Đọc lại dữ liệu sử dụng header=T

> a <- read.table('d:/car.txt', sep=';', header=T) > a make model mpg weight price 1 AMC Concord 22 2930 4099 2 AMC Pacer 17 3350 4749 3 AMC Spirit 22 2640 3799 4 Buick Century 20 3250 4816 5 Buick Electra 15 4080 7827

Xem nội dung cột model

> a$model [1] Concord Pacer Spirit Century Electra Levels: Century Concord Electra Pacer Spirit

Có thể sử dụng a[2], hoặc a[“model”], nhưng thông tin ít hơn (chỉ có dữ liệu mà không có Levels)

> a[2] model 1 Concord 2 Pacer 3 Spirit 4 Century 5 Electra > a['model'] model 1 Concord 2 Pacer 3 Spirit 4 Century 5 Electra

Tìm xe có giá lớn nhất = tính max của cột price

> max(a['price']) [1] 7827

Giá trung bình của một chiếc xe là:

> sum(a['price']) / length(a[,1]) # tổng giá chia cho số xe = giá trung bình

22/35

[1] 5058

Thay đổi giá (price) của chiếc xe thứ 1

> a[1,5] <- 4091 > a[1,5] [1] 4091 > a[1, 'price'] # ta cũng có thể sử dụng tên cột thay cho chỉ số cột [1] 4091 3.2. Xây dựng mô hình dự báo

Giờ ta sẽ thử xem có thể dự báo được hãng sản xuất (cột made) nếu biết khối lượng (weight) và giá (price) hay không.

Bỏ qua tất cả các cột khác, xây dựng mô hình KNN để phân loại xe (cột made được xem như nhãn) dựa vào thông tin về khối lượng (weight) và giá (price).

> nrow <- length(a[, 1]) # số phần tử trong tập dữ liệu a > nrow [1] 5 > idx <- sample(nrow, nrow, replace=F) # lấy mẫu nrow phần tử từ 1 đến nrow > idx [1] 1 4 2 5 3 > trainrow <- nrow – 1 # lấy 4 phần tử để làm tập học > trainrow [1] 4 > trainset <- a[idx[1:trainrow], ] > trainset make model mpg weight price 1 AMC Concord 22 2930 4091 4 Buick Century 20 3250 4816 2 AMC Pacer 17 3350 4749 5 Buick Electra 15 4080 7827 > testset <- a[idx[(trainrow + 1):nrow], ] > testset # 1 phần tử còn lại để làm tập kiểm tra make model mpg weight price 3 AMC Spirit 22 2640 3799 > library(class) # nạp thư viện class để sử dụng knn # dự báo nhãn của tập test (cột make) # dựa vào 2 cột 4, 5 (weight và price) > pred <- knn(trainset[, 4:5], testset[, 4:5], trainset[, 1], k=1) > pred [1] AMC # máy dự báo ra nhãn của test là AMC Levels: AMC Buick > pred == testset[,1] # kiểm tra lại xem dự báo đúng không [1] TRUE # TRUE: rất là Ok

>

23/35

Kết quả này cho thấy rằng có thể dựa vào khối lượng và giá cả mà dự báo hãng sản xuất xe !

3.3. Kho dữ liệu cho Data mining và Học máy

UCI là kho dữ liệu được cộng đồng Khai khoáng dữ liệu và Học máy sử dụng nhiều để kiểm tra đánh giá các giải thuật Khai khoáng dữ liệu. Một số tập dữ liệu đã được tích hợp sẵn trong R (ví dụ như Iris). Các tập dữ liệu trên UCI thường ở dạng văn bản (Text) vì thế ta có thể dễ dàng đọc lên để xử lý bằng hàm read.table.

Vào trang web UCI: http://archive.ics.uci.edu/ml/ (chứa các tập dữ liệu dùng để kiểm thử các giải thuật máy học, khai khoáng dữ liệu). Xem cột bên phải (từ năm 2007). Mỗi mục là 1 tập dữ liệu.

Ví dụ ta chọn tập dữ liệu Wine (rượu vang).

24/35

Xem mô tả của tập dữ liệu trong bảng trên: Dữ liệu nhiều chiều (Multivariate); thuộc tính kiểu số nguyên, số thực; Bài toán: phân lớp (Classification); Số phần tử: 178; số thuộc tính: 13; Giá trị thiếu: không có; … Click Data Set Description để xem thêm thông tin mô tả về tập dữ liệu này. Xem thông tin thêm ta biết được cột đầu tiên là nhãn của dữ liệu và có 3 nhãn khác nhau. Download dữ liệu (file *.data) về và lưu trong thư mục nào đó, ví dụ: C:\R-data Ví dụ: ta download file wine.data

Vào R, đọc file dữ liệu này lên (hàm read.table). Chú ý dữ liệu này không có HEADER, ký tự phân cách là dấu phẩy (,) Ví dụ: D <- read.table(‘C:/R-data/wine.data’, sep=’,’) Lúc này D sẽ chứa toàn bộ bảng dữ liệu sẵn sàng để phân tích, xử lý. 3.4. Giải thuật k láng giềng (k-NN)

Giải thuật k-NN không có quá trình học mà chỉ có quá trình dự báo/phân lớp (Xem lại lý thuyết về giải thuật k-NN). Trong phần này ta sẽ cài đặt giải thuật k-NN bằng ngôn ngữ R và sau đó so sánh với giải thuật k-NN của thư viện class.

25/35

Soạn thảo 1 script mới. Viết hàm my.knn(trainset, testset, label, k)

Với các tham số:

• trainset: tập học không chứa nhãn • testset: tập kiểm tra không chứa nhãn • label: nhãn của tập học • k: số láng giềng

Giải thuật:

Với mỗi phần tử testset[i, ], ta tính khoảng cách của nó đến các phần tử trong trainset, lưu lại khoảng cách và nhãn của các phần trong trainset vào trong bảng kc (khoảng cách) có 2 cột: khoảng cách và nhãn.

Sắp xếp kc tăng dần theo khoảng cách.

Lấy k phần tử đầu tiên trong kc (sau khi đã sắp xếp)

Thống kê xem nhãn nào xuất hiện nhiều nhất => đây chính là nhãn của testset[i, ]

26/35

Thử nghiệm, hàm my.knn trên tập dữ liệu iris

#Viết hàm tính khoảng cách của 2 véctơ x và y

dist2 <- function(x, y) { ???????? #tính bình phương khoảng cách x, y } my.knn <- function(trainset, testset, class, k) { trainrow <- length(trainset[,1]) testrow <- length(testset[,1]) kc <- rep(0,trainrow) #Tạo mảng lưu khoảng cách kq <- rep("", testrow) #Lưu nhãn dự báo for (i in 1:testrow) { for (j in 1:trainrow) { kc[j] <- dist2(testset[i,], trainset[j,]) } idx <- ?????? #Sắp xếp khoảng cách tăng dần idx1 <- ????? #Lấy ra k phần tử đầu tiên (gần nhất) #Thống kê nhãn của k phần tử gần nhất bang <- ????????? #Gợi ý: sử dụng hàm table trên class #Sắp xếp số lần xuất hiện của nhãn bang_sx <- ????? #Gợi ý: sử dụng hàm sort #Lấy ra nhãn xuất hiện nhiều nhất kq[i] <- ???? #Gợi ý: sử dụng hàm names } #Trả kết quả cho hàm kq }

27/35

Bài tập yêu cầu: 1. Vào trang UCI, chọn 1 tập dữ liệu bất kỳ (khác IRIS), download về máy, viết các lệnh cần thiết để đọc tập dữ liệu này lên R

2. Viết các lệnh để xem số phần tử, số thuộc tính. Cho biết kết quả của các lệnh này. 3. Hoàn chỉnh hàm my.knn (hoặc tự viết mới hàm my.knn) sao cho có thể thực thi được. (Nếu

không thể hoàn chỉnh được hàm my.knn các câu bên dưới sẽ sử dụng giải thuật knn của R) Gợi ý thêm: khi dùng hàm table để đếm tần số ta sẽ thu dược bảng có dạng sau:

setosa versicolor virginica 1 2 0

Hàng trên cùng là tên cột nên có thể dung hàm names đê truy xuất. Khi sắp xếp bảng thì các cột cũng sẽ thay đổi vị trí cho phù hợp. 4. Chạy thực nghiệm trên tập iris, cho viết kết quả thu được. 5. Vào lại trang UCI, tìm thêm 1 tập dữ liệu khác có thể chạy được với giải thuật k-NN. Download

tập dữ liệu đó về, chạy lại với knn và my.knn cho biết độ chính xác của mỗi lần chạy. 6. Làm thế nào để có thể so sánh knn và my.knn trên các tập dữ liệu trên ? 7. Cho biết tiêu chí chọn tập dữ liệu của bạn. Thay đổi hàm tính khoảng cách dist2 thành dist1 với khoảng cách L1

dist1(x, y) = |x1 –y1| + |x2 – y2| + … |xn – yn| 8. Viết ra định nghĩa của hàm dist1 trong R 9. Chạy lại my.knn trên iris với khoảng cách là hàm dist1, so sánh với dist2 (mỗi khoảng cách thực

nghiệm 10 lần và lấy độ chính xác trung bình) 10. Viết đoạn lệnh để thực thi câu 9 tự động (sử dụng for).

#Kiểm tra độ chính xác của my.knn

data(iris) library(class) nrow <-length(iris[,1]) ncol <- length(iris[1,]) trainrow <- round(nrow*2/3) idx <- sample(nrow, replace=F) trainset <- iris[idx[1:trainrow], ] testset <- iris[idx[(trainrow+1): nrow], ] pred1 <- knn(trainset[,-ncol], testset[,-ncol], trainset[,ncol], k=3) pred2 <- my.knn(trainset[,-ncol], testset[,-ncol], trainset[,ncol], k=3) print(sum(pred1 == pred2)/(nrow - trainrow))

28/35

Mã nguồn tham khảo của giải thuật kNN với khoảng cách euclide. Đề nghị không xem mã nguồn trước khi thực hiện các câu từ 1 - 7.

#Viết hàm tính khoảng cách của 2 véctơ x và y

dist2 <- function(x, y) { sum((x – y)^2) #tính bình phương khoảng cách } my.knn <- function(trainset, testset, class, k) { trainrow <- length(trainset[,1]) testrow <- length(testset[,1]) kc <- rep(0,trainrow) #Tạo mảng lưu khoảng cách kq <- rep("", testrow) #Lưu nhãn dự báo for (i in 1:testrow) { for (j in 1:trainrow) { kc[j] <- dist2(testset[i,], trainset[j,]) } idx <- order(kc) #Sắp xếp khoảng cách idx1 <- idx[1:k] #Lấy ra k phần tử đầu tiên (gần nhất) #Thống kê nhãn của k phần tử gần nhất bang <- table(class[idx1]) #Sắp xếp số lần xuất hiện của nhãn bang_sx <- sort(bang, decreasing=T) #Lấy ra nhãn xuất hiện nhiều nhất kq[i] <- names(bang_sx)[1] } #Trả kết quả cho hàm kq }

29/35

BUỔI 3. CÂY QUYẾT ĐỊNH

Mục tiêu: • Sử dụng giải thuật cây quyết định được cài đặt trong R • Hiểu nguyên lý hoạt động của giải thuật xây dựng cây quyết định. • Cài đặt cây quyết định trong R.

3.5. Cây quyết định

1. Cài đặt gói tree (nếu gói này chưa được cài đặt) : xem hướng dẫn cài đặt các gói trong phần R căn bản

2. Sử dụng cây Quyết định trong R a. Gõ lại chương trình ví dụ trang 30. Cho biết độ chính xác bằng bao nhiêu ? Nút gốc

sử dụng thuộc tính nào để phân hoạch và điểm cắt v = bao nhiêu ? b. Thay đổi minsize = 2, cho biết độ chính xác bằng bao nhiêu. c. Thay đổi minsize = 3, cho biết độ chính xác bằng bao nhiêu. d. Thay đổi minsize = 4, cho biết độ chính xác bằng bao nhiêu. e. Thay đổi minsize = 5, cho biết độ chính xác bằng bao nhiêu. f. Thay đổi minsize = 6, cho biết độ chính xác bằng bao nhiêu. g. Thay đổi minsize = 7, cho biết độ chính xác bằng bao nhiêu. h. Thay đổi minsize = 8, cho biết độ chính xác bằng bao nhiêu. i. Thay đổi minsize = 9, cho biết độ chính xác bằng bao nhiêu. j. Thay đổi minsize = 10, cho biết độ chính xác bằng bao nhiêu. k. Vẽ đồ thị với trục x là minsize, trục y là độ chính xác thu được từ câu a đến câu j l. Viết mã lệnh để thực hiện các câu từ a – k một cách tự động (gợi ý: sử dụng lệnh for)

3. Vào UCI, chọn 3 tập dữ liệu bất kỳ. Chạy giải thuật cây quyết định trên các tập này. So sánh kết quả đạt được so với giải thuật kNN. Với mỗi tập dữ liệu, chọn 2/3 làm tập học, 1/3 còn lại làm tập kiểm tra. Lập bảng so sánh 2 giải thuật trên 3 tập dữ liệu này.

4. Củng cố lý thuyết : trong phần này ta sẽ kiểm tra nguyên lý hoạt động của giải thuật cây quyết định đã được cài đặt trong gói tree.

a. Cho biết chương trình trong trang 30 sử dụng tiêu chí gì để thực hiện phân hoạch các nút ? Nếu muốn sử dụng tiêu chí khác thì làm thế nào ? (Sử dụng lệnh help hoặc tìm kiếm trên Internet)

b. Nạp dữ liệu iris (lệnh data(iris)) c. Viết lệnh sắp xếp tập dữ liệu iris theo thứ tự tăng dần của cột 1. (Gợi ý: dùng lệnh

order để sắp xếp và lấy chỉ số. Dùng các chỉ số để truy xuất các phần tử theo thứ tự.) Ví dụ:

idx <- order(iris[,1]) T <- iris[idx,]

T chứa dữ liệu của iris được sắp xếp theo cột 1. d. Chia dữ liệu làm 2 (cắt ngay chính giữa) gán phần trên vào biến T1, phần dưới vào

biến T2. e. Tính gini của phần T1 bằng cách đếm số phần tử thuộc lớp setosa, số phần tử thuộc

lớp versicolor và số phần tử thuộc lớp virginica. Áp dụng công thức Gini = 1 – (p12 +

p22 + p3

2 + … + pn2).

Gợi ý: để đếm các giá trị của 1 cột dùng hàm table. Ví dụ table(iris[,5]) sẽ cho ra số phần tử của các giá trị khác nhau của cột 5 (cột class). Ta sẽ nhận được 50-50-50.

f. Tương tự tính gini cho phần T2. Gợi ý: sử dụng hàm sum để cộng các phần tử của 1 véc-tơ.

g. Từ kết quả câu d và e tính gini của iris tại điểm cắt này.

30/35

h. Viết chương trình thực hiện tự động từ câu b đến câu f (Đoạn mã bên dưới thực hiện ự động từ câu b đến câu f) : Hãy chỉ ra đoạn mã nào tương ứng với câu nào ?

i. Viết chương trình tính gini của cột 1 của tập dữ liệu iris. Gợi ý : Thay đổi giá trị v từ 1 đến (nrow - 1), tính lại gini tại các điểm cắt này. Tìm ra vị trí cắt và giá trị cắt của thuộc tính (giá trị cắt là giá trị tại vị trí cho gini NHỎ nhất). Sử dụng vòng lặp for (v in 1:(nrow - 1)), trong mỗi vòng lặp so sánh gini thu được với giá trị nhỏ nhất.

#nạp dữ liệu iris data(iris) #lấy số phần tử của iris nrow <- length(iris[,1]) ncol <- length(iris[1,]) #lấy thứ tự tăng dần theo cột 1 idx <- order(iris[,1]) #sắp xếp thứ tự theo cột 1 và gán vào biến T T <- iris[idx,] #Chia T thành 2 phần tại vị trí v = chính giữa v <- round(nrow/2) T1 = T[1:v, ] T2 <- T[(v+1):nrow, ] #Tinh tong so phan tu cua T1 và T2 n1 <- v n2 <- nrow - v #Tinh gini cho T1 #Dem so gia tri cua cot nhan freq1 <- table(T1[,ncol]) #chia tan so cho so phan tu -> thu duoc bang phan phoi xs p1 <- freq1/n1 #gini cua T1 = 1 - tong binh phuong cua cac phan tu trong p1 gini1 = 1 - sum(p1^2) #Tinh gini cho T2 #Dem so gia tri cua cot nhan freq2 <- table(T2[,ncol]) #chia tan so cho so phan tu -> thu duoc bang phan phoi xs p2 <- freq2/n2 #gini cua T2 = 1 - tong binh phuong cua cac phan tu trong p2 gini2 = 1 - sum(p2^2) #Tinh gini cho T tai vi tri v gini <- (n1*gini1 + n2*gini2)/(n1 + n2) print(gini)

31/35

j. Viết chương trình tính gini của 1 cột bất kỳ của tập iris. Áp dụng tính gini cho cả 4 cột từ đó suy ra phải chọn thuộc tính nào cho nút gốc ? Và giá trị cắt cho thuộc tính đó bằng bao nhiêu ? Gợi ý: sử dụng vòng lặp for (tt in 1:ncol), trong mỗi vòng lặp thay tt vào hàm order.

k. Kiểm chứng lại kết quả bằng cách xây dựng mô hình cây quyết định (lệnh tree) trên toàn bộ tập iris (thay trainset bằng iris). Dùng plot(model); text(model) để xem kết quả.

32/35

BUỔI 4. BAYES NGÂY THƠ

Mục tiêu: • Sử dụng giải thuật Bayes được cài đặt trong R • Hiểu nguyên lý hoạt động của giải thuật xây dựng mô hình Bayes ngây thơ. • Cài đặt giải thuật Bayes ngây thơ bằng ngôn ngữ R.

3.6. Bayes ngây thơ (Naïve Bayes)

1. Cài đặt gói e1071 và gói class (nếu gói này chưa được cài đặt) : xem hướng dẫn cài đặt các gói trong phần R căn bản.

2. Vào UCI Download 3 tập dữ liệu bất kỳ (nên chọn các tập dữ liệu khác với các tập dữ liệu đã chọn trước đây để có thêm thông tin về dữ liệu), thực hiện giải thuật Bayes thơ ngây trên các tập dữ liệu này và so sánh với giải thuật Cây quyết định. Với mỗi tập dữ liệu lấy ngẫu nhiên 2/3 làm tập học 1/3 còn lại làm tập kiểm tra.

3. Dùng một trình soạn thảo bất kỳ (notepad chẳng hạn) nhập bảng dữ liệu chơi golf và lưu vào file (ví dụ: C:\golf.txt), vào R đọc dữ liệu này lên và lưu vào biến golf.

4. Dùng R tính xác suất có điều kiện P(Outlook/Play = “yes”). Bảng phân phối xác suất có dạng

Outlook/Play = yes sunny overcast rainny P Gợi ý : a. Tìm giá trị Outlook của các phần tử có Play = “yes”

val <- golf[golf[,5] = “yes”, 1] trong đó 1 tương ứng với cột Outlook (có thể sử dụng tên cột để truy xuất thay cho chỉ số cột), 5 là cột Play. b. Thống kê tần số xuất hiện của các giá trị, chuẩn hoá cho tổng bằng 1 => bảng phân phối xác suất. P1.1 <- table(val) # thống kê tấn số xuất hiện P1.1 <- P1.1/sum(P1.1) # chuẩn hoá P1.1 sẽ lưu giữ bảng phân phối xác suất có điều kiện của Outlook khi biết giá trị Play = yes

5. Tương tự câu 4 tính, xác suất P(Outlook/Play= “no”) lưu vào biến P1.2 6. Lặp lại các câu 4, 5 cho cột Humidity gán vào các biến: P2.1, P2.2 7. Lặp lại các câu 4, 5 cho cột Temperature gán vào các biến: P3.1, P3.2

Outlook,Temperature,Humidity,Windy,Play sunny,hot,high,false,no sunny,hot,high,true,no overcast,hot,high,false,yes rainy,mild,high,false,yes rainy,cool,normal,false,yes rainy,cool,normal,true,no overcast,cool,normal,true,yes sunny,mild,high,false,no sunny,cool,normal,false,yes rainy,mild,normal,false,yes sunny,mild,normal,true,yes overcast,mild,high,true,yes overcast,hot,normal,false,yes rainy,mild,high,true,no

33/35

8. Lặp lại các câu 4, 5 cho cột Windy gán vào các biến: P4.1, P4.2 9. Tính xác suất P(Play), lưu vào biến P 10. Sử dụng các bảng xác suất trên dự báo nhãn cho dữ liệu

X = (“rainy”, “cool”, “high”, “false”) Nhận xét: các câu từ 4 – 8 tính xác xuất P(Outlook/Play = “yes”) và P(Outlook/Play = “no”) một cách riêng lẻ. Ta có thể sử dụng hàm table để tính P(Outlook/Play = “Yes”) và P(Outlook/Play = “No”) đồng thời:

outlook <- table(golf[, “Outlook”], golf[, “Play”]) hoặc outlook <- table(golf[, 1], golf[, 5])

Chuẩn hoá tần số xuất hiện thành xác suất bằng cách chia cho tổng các cột tương ứng p.outlook <- prop.table(outlook, 2) trong đó 2 có nghĩa là chuẩn hoá các cột. Có thể thử prop.table(outlook, 1) xem kết quả thế nào. Ta có thể viết đoạn chương trình này thành hàm và sử dụng trong các câu sau, ví dụ:

11. Sử dụng hàm ct bên trên để tính P(Outlook/Play = “yes”) và P(Outlook/Play = “no”) đồng

thời và lưu vào biến P.Outlook 12. Tương tự câu 11, tính P.Temperature 13. Tương tự câu 11, tính P.Humidity 14. Tương tự câu 11, tính P.Windy 15. Nâng cao: Tìm một cấu trúc dữ liệu hợp lý để lưu trữ các bảng xác suất trên sao cho việc truy

xuất được thực hiện dễ dàng thông qua tên cột và giá trị của cột (có thể sử dụng kiểu list). Ví dụ:

bayes.model <- list(P.Outlook, P.Temperature, P.Humidity, P.Windy, P) Với P tính được từ câu 9.

Để thêm một phần tử mới vào cuối danh sách ta có thể sử dụng lệnh c. Ví dụ: bayes.model <- list(P.Outlook, P.Temperature, P.Humidity, P.Windy) bayes.model <- c(bayes.model, list(P))

Đặt tên cho các phần tử của bayes.model names(bayes.model) <- c(“Outlook”, “Temperature”, “Humidity”, “Windy”, “Play”) hoặc names(bayes.model) <- names(golf) Để tính P(Outlook = “sunny” / Play = “yes”) ta truy xuất

bayes.model[“Outlook”] [“sunny”, “yes”]

Viết hàm myNaiveBayes(data, label) trả về mô hình Bayes ngây thơ có cấu trúc như biến bayes.model. Các tham số: data là dữ liệu không nhãn, label là cột nhãn. Giả sử dữ liệu đang xét là dữ liệu ký hiệu. Khai báo hàm như sau:

ct <- function(data, att, class) { freq <- table(data[, att], data[, class]) prop.table(freq, 2) }

myNaiveBayes <- function(data, label) { #viết nội dung hàm ở đây }

34/35

16. Nâng cao: viết hàm myPredict nhận vào dữ liệu kiểm tra và mô hình sinh ra từ câu 15, dự

báo nhãn cho dữ liệu mới này. Dữ liệu số, liên tục: sử dụng phân phối Gauss

17. Đọc dữ liệu iris 18. Tính trung bình và độ lệch chuẩn của cột 1 trong trường hợp nhãn = “setosa” 19. Tính trung bình và độ lệch chuẩn của cột 1 trong trường hợp nhãn = “vericolor” 20. Tính trung bình và độ lệch chuẩn của cột 1 trong trường hợp nhãn = “verginica” 21. Lặp lại các câu 18 – 20 cho cột 2 22. Lặp lại các câu 18 – 20 cho cột 3 23. Lặp lại các câu 18 – 20 cho cột 4 24. Tính xác suất của cột nhãn (cột 5): xem câu 9. 25. Sử dụng các giá trị trung bình và độ lệch chuẩn ở trên, dự báo nhãn cho dữ liệu:

X = (5.7, 3.8, 1.4, 0.3)

Gợi ý: sử dụng hàm mật độ xác suất của phân phối chuẩn: 𝑓 𝑥 = !!!"!

𝑒! !!! !

!!! Tính f(Sepal.Length = 5.7/Species = ‘setosa’) Tính f(Sepal.Width = 3.8/Species = ‘setosa’) Tính f(Petal.Length = 1.4/Species = ‘setosa’) Tính f(Petal.Width = 0.3/Species = ‘setosa’) Tương tự, Tính f(Sepal.Length = 5.7/Species = ‘versicolor’) Tính f(Sepal.Width = 3.8/Species = ‘versicolor’) Tính f(Petal.Length = 1.4/Species = ‘versicolor’) Tính f(Petal.Width = 0.3/Species = ‘versicolor’) Tính f(Sepal.Length = 5.7/Species = ‘virginica’) Tính f(Sepal.Width = 3.8/Species = ‘virginica’) Tính f(Petal.Length = 1.4/Species = ‘virginica’) Tính f(Petal.Width = 0.3/Species = ‘virginica’) Từ đó suy ra nhãn của X.

26. Nâng cao: Viết hàm myNaiveBayesNum(data, label) trả về mô hình Bayes ngây thơ trong

trường hợp dữ liệu số. 27. Nâng cao: Viết hàm myPredictNum(model, newdata) trả về nhãn của newdata với model thu được từ câu 26.

28. Nâng cao: Viết hàm myNaiveBayesMixed(data, label) trả về mô hình Bayes ngây thơ trong trường hợp dữ liệu hỗ hợp: gồm cả kí hiệu và số.

29. Nâng cao: Viết hàm myPredictMixed(model, newdata) trả về nhãn của newdata với model thu được từ câu 28.

35/35

BUỔI 5. ÔN TẬP

Mục tiêu: Củng cố tất cả các bài thực hành ở các buổi trước.

Nội dung:

• R căn bản: phép toán số học, véc-tơ, ma trận • R cho mining: khung dữ liệu, đọc, ghi khung dữ liệu, sắp xếp, tìm kiếm, lấy mẫu, … • Một số giải thuật dùng để khai khoáng dữ liệu: kNN, Bayes ngây thơ, cây quyết định