Chuyển đến nội dung chính

Tiền xử lý trong Khoa học Dữ liệu (Phần 1): Đưa về trung tâm, Chuẩn hóa và KNN

Bài viết này sẽ giải thích tầm quan trọng của tiền xử lý trong quy trình máy học bằng cách xem xét cách đưa về trung tâm và chuẩn hóa có thể cải thiện hiệu năng mô hình.
· 11 phút đọc

Khám phá cùng AI

Tiền xử lý dữ liệu là một thuật ngữ bao trùm để chỉ nhiều thao tác mà các nhà khoa học dữ liệu sử dụng nhằm đưa dữ liệu về dạng phù hợp hơn với mục đích phân tích. Ví dụ, trước khi phân tích cảm xúc trên dữ liệu Twitter, bạn có thể muốn loại bỏ mọi thẻ HTML, khoảng trắng thừa, mở rộng các chữ viết tắt và tách tweet thành danh sách các từ chứa trong đó. Khi phân tích dữ liệu không gian, bạn có thể chuẩn hóa để dữ liệu độc lập với đơn vị đo, tức là thuật toán không quan tâm liệu số đo ban đầu là dặm hay centimet. Tuy nhiên, tiền xử lý dữ liệu không diễn ra trong chân không. Điều này có nghĩa tiền xử lý là phương tiện để đạt mục tiêu và không có quy tắc cứng nhắc: có các thực hành tiêu chuẩn, như chúng ta sẽ thấy, và bạn có thể phát triển trực giác về cái gì hiệu quả, nhưng nhìn chung tiền xử lý là một phần của một chuỗi xử lý hướng kết quả và cần được đánh giá hiệu quả trong bối cảnh.

Trong bài viết này, tôi sẽ dùng ví dụ về việc chuẩn hóa dữ liệu số (dữ liệu số: dữ liệu gồm các con số, trái với dữ liệu phân loại/chuỗi; chuẩn hóa/scaling: dùng các phép toán cơ bản để thay đổi khoảng giá trị của dữ liệu; chi tiết sẽ ở phần sau) để minh họa tầm quan trọng của việc xem tiền xử lý như một phần của cấu trúc lớn hơn: quy trình máy học (ML). Để làm rõ, chúng ta sẽ xem một ví dụ thực tế trong đó việc chuẩn hóa có thể cải thiện hiệu năng mô hình.

Trước hết, tôi sẽ giới thiệu bài toán phân loại trong ML và k-láng giềng gần nhất (k-Nearest Neighbors), một trong những thuật toán đơn giản nhất dùng trong bối cảnh này. Để hiểu tầm quan trọng của việc chuẩn hóa dữ liệu số trong bối cảnh đó, tôi sẽ giới thiệu các thước đo hiệu năng mô hình cùng khái niệm tập huấn luyện và tập kiểm tra. Bạn sẽ thấy tất cả các khái niệm và thực hành này được áp dụng với một tập dữ liệu mà tôi cố gắng phân loại chất lượng rượu vang đỏ. Tôi cũng sẽ đặt tiền xử lý vào vị trí hữu ích nhất của nó: gần phần đầu của quy trình khoa học dữ liệu lặp. Tất cả ví dụ đều dùng Python. Nếu bạn chưa quen với Python, bạn có thể xem các khóa học của DataCamp tại đây. Tôi sẽ sử dụng thư viện pandas cho nhu cầu về dataframe và scikit-learn cho nhu cầu về máy học.

Đây là phần một của loạt hướng dẫn ba phần:

Phần 2: Đưa về trung tâm, Chuẩn hóa và Hồi quy Logistic

Phần 3: Chuẩn hóa Dữ liệu Tổng hợp

Lược giới thiệu về các bài toán phân loại trong Máy học

Phân loại và gán nhãn các sự vật trong thế giới hiện tượng là một nghệ thuật lâu đời. Vào thế kỷ 4 TCN, Aristotle đã xây dựng một hệ thống phân loại sinh vật được sử dụng trong 2.000 năm. Ngày nay, phân loại thường được coi là một nhiệm vụ máy học, cụ thể là một nhiệm vụ học có giám sát. Nguyên lý cơ bản của học có giám sát rất đơn giản: chúng ta có một loạt dữ liệu gồm các biến dự đoán và một biến đích. Mục tiêu của học có giám sát là xây dựng một mô hình "giỏi" dự đoán biến đích dựa trên các biến dự đoán. Nếu biến đích gồm các hạng mục (ví dụ 'nhấp' hoặc 'không', khối u 'ác tính' hoặc 'lành tính'), ta gọi nhiệm vụ học này là phân loại. Ngược lại, nếu biến đích là biến thay đổi liên tục (ví dụ giá nhà), đó là nhiệm vụ hồi quy.

Một ví dụ minh họa sẽ rất hữu ích: hãy xem tập dữ liệu bệnh tim, trong đó có 75 biến dự đoán như 'tuổi', 'giới tính' và 'có hút thuốc hay không', còn biến đích cho biết sự hiện diện của bệnh tim với thang điểm từ 0 (không bệnh tim) đến 4. Nhiều nghiên cứu về tập dữ liệu này tập trung vào việc phân biệt có bệnh tim hay không. Đây là một bài toán phân loại. Nếu bạn cố gắng dự đoán giá trị thực (0 đến 4) của biến đích, đó sẽ là một bài toán hồi quy (vì biến đích có thứ tự). Tôi sẽ bàn về hồi quy trong bài viết tiếp theo. Ở đây tôi sẽ xem một trong những thuật toán đơn giản nhất cho bài toán phân loại, thuật toán k-láng giềng gần nhất.

k-láng giềng gần nhất cho phân loại trong máy học

Giả sử chúng ta có một số dữ liệu đã gán nhãn, ví dụ dữ liệu gồm các đặc tính của rượu vang đỏ (như độ cồn, mật độ, lượng axit citric, pH, v.v.; đây là các biến dự đoán) với biến đích 'Chất lượng' và nhãn 'tốt' & 'xấu'. Khi đó, với đặc tính của một mẫu rượu mới chưa có nhãn, nhiệm vụ phân loại là dự đoán 'Chất lượng' của nó. Khi tất cả biến dự đoán là số (cũng có cách xử lý biến phân loại), ta có thể coi mỗi hàng/mẫu rượu là một điểm trong không gian n chiều và, trong trường hợp này, k-láng giềng gần nhất (k-NN) là một phương pháp phân loại đơn giản về mặt khái niệm & tính toán: với mỗi mẫu rượu mới chưa có nhãn, ta tính, với một số nguyên k nào đó, k láng giềng gần nhất của nó trong không gian biến dự đoán n chiều. Sau đó ta xem nhãn của k láng giềng này (tức 'tốt' hay 'xấu') & gán cho rượu mới nhãn có số phiếu nhiều nhất (ví dụ nếu k = 5, có 3 láng giềng bình chọn 'tốt' và 2 bình chọn 'xấu', thì mô hình gán nhãn 'tốt'). Lưu ý rằng, ở đây, huấn luyện mô hình chỉ gồm việc lưu trữ các điểm dữ liệu: không có tham số nào cần ước lượng!

Mô tả trực quan về k-láng giềng gần nhất

Trong hình dưới đây là ví dụ k-NN trong không gian 2D: bạn sẽ phân loại điểm dữ liệu ở giữa như thế nào? Nếu k=3, bạn sẽ phân loại nó là đỏ và nếu k=5, là xanh lục.

 
ví dụ k-nn trong 2d

Triển khai k-NN trong Python (scikit-learn)

Bây giờ hãy xem một ví dụ k-NN hoạt động ra sao. Chúng ta sẽ thử với tập dữ liệu chất lượng rượu vang: nhập dữ liệu vào một dataframe của pandas rồi vẽ biểu đồ tần suất của các biến dự đoán để cảm nhận dữ liệu.
import pandas as pd%matplotlib inlineimport matplotlib.pyplot as pltplt.style.use('ggplot')df = pd.read_csv('http://archive.ics.uci.edu/ml/machine-learning-databases/wine-quality/winequality-red.csv ' , sep = ';')X = df.drop('quality' , 1).values # drop target variabley1 = df['quality'].valuespd.DataFrame.hist(df, figsize = [15,15]);
biểu đồ cột

Trước hết, hãy để ý khoảng giá trị của các biến dự đoán: 'free sulfur dioxide' dao động từ 0 đến khoảng 70 và 'volatile acidity' từ khoảng 0 đến khoảng 1,2. Cụ thể hơn, biến thứ nhất có khoảng giá trị lớn hơn biến thứ hai 2 bậc độ lớn. Bất kỳ thuật toán nào, như k-NN, vốn quan tâm đến khoảng cách giữa các điểm dữ liệu, có thể sẽ tập trung quá mức và thiếu công bằng vào các biến có khoảng giá trị lớn hơn, như 'free sulfur dioxide' — vốn có thể chỉ toàn nhiễu, ai mà biết được. Điều này thúc đẩy việc chuẩn hóa dữ liệu, và chúng ta sẽ sớm làm điều đó.

Giờ biến đích là xếp hạng 'Chất lượng' của rượu vang, từ 3 đến 8. Để trình bày cho gọn, hãy chuyển nó thành biến hai hạng mục gồm 'tốt' (điểm > 5) & 'xấu' (điểm <= 5). Chúng ta cũng sẽ vẽ biểu đồ tần suất cho cả hai cách biểu diễn biến đích để hình dung rõ hơn.

y = y1 <= 5 # is the rating <= 5?# plot histograms of original target variable# and aggregated target variableplt.figure(figsize=(20,5));plt.subplot(1, 2, 1 );plt.hist(y1);plt.xlabel('original target value')plt.ylabel('count')plt.subplot(1, 2, 2);plt.hist(y)plt.xlabel('aggregated target value')plt.show()
biểu đồ cột
Giờ thì chúng ta gần như sẵn sàng chạy k-láng giềng gần nhất. Tuy nhiên, nếu muốn so sánh hiệu năng mô hình giữa có và không tiền xử lý, chúng ta cần xác định cách đo "độ tốt" của mô hình:

k-láng giềng gần nhất: hiệu năng thế nào?

Có nhiều thước đo hiệu năng cho các bài toán phân loại. Điều cực kỳ quan trọng là phải nhận ra lựa chọn thước đo hiệu năng phụ thuộc sâu sắc vào miền bài toán & câu hỏi cụ thể. Với tập dữ liệu có các lớp cân bằng (mọi giá trị đích đều được đại diện xấp xỉ ngang nhau), các nhà khoa học dữ liệu thường xem xét độ chính xác làm thước đo. Thực tế, như chúng ta sẽ thấy, độ chính xác là phương pháp chấm điểm mặc định cho cả k-láng giềng gần nhất và hồi quy logistic trong scikit-learn. Vậy độ chính xác là gì? Chỉ đơn giản là số dự đoán đúng chia cho tổng số dự đoán:
$$\text{Accuracy}=\frac{\text{Number of Correct Predictions}}{\text{Total Number of Predictions}}.$$

Lưu ý: độ chính xác cũng có thể được định nghĩa theo ma trận nhầm lẫn và thường được định nghĩa cho bài toán phân loại nhị phân theo số dương tính thật & âm tính giả; các thước đo hiệu năng phổ biến khác suy ra từ ma trận nhầm lẫn gồm độ chuẩn xác (precision), số dương tính thật chia cho tổng dương tính thật & dương tính giả, và độ bao phủ (recall), số dương tính thật chia cho tổng dương tính thật cộng âm tính giả; một thước đo khác, điểm F1, là trung bình điều hòa của precision và recall. Xem machine learning mastery để có phần giải thích rõ ràng về các thước đo này; cũng xem mục Wikipedia về ma trận nhầm lẫn và điểm F1.

k-láng giềng gần nhất: hiệu năng thực tế và phép chia train-test

Có thước đo như độ chính xác là điều tốt, nhưng nếu chúng ta fit mô hình trên toàn bộ dữ liệu, thì ta sẽ báo cáo độ chính xác trên tập dữ liệu nào? Hãy nhớ rằng chúng ta muốn mô hình khái quát hóa tốt trên dữ liệu mới. Do đó, nếu ta huấn luyện mô hình trên một tập dữ liệu D, việc báo cáo độ chính xác của mô hình trên chính tập dữ liệu D có thể khiến nó trông như hoạt động tốt hơn thực tế. Điều này gọi là overfitting. Để khắc phục, các nhà khoa học dữ liệu thường huấn luyện mô hình trên một phần dữ liệu, gọi là tập huấn luyện và đánh giá hiệu năng trên phần còn lại, tức tập kiểm tra. Đây chính là điều chúng ta sẽ làm! Một kinh nghiệm thường dùng là dành khoảng 80% dữ liệu cho huấn luyện & 20% cho kiểm tra. Hãy tách dữ liệu chất lượng rượu vang đỏ của chúng ta:
from sklearn.cross_validation import train_test_splitX_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)We now build the k-NN model, make predictions on the test set and compare these predictions to the ground truth in order to get a measure of model performance:from sklearn import neighbors, linear_modelknn = neighbors.KNeighborsClassifier(n_neighbors = 5)knn_model_1 = knn.fit(X_train, y_train)print('k-NN accuracy for test set: %f' % knn_model_1.score(X_test, y_test))k-NN accuracy for test set: 0.612500

Đáng nhắc lại rằng phương pháp chấm điểm mặc định cho k-NN trong scikit-learn là
độ chính xác. Độ chính xác 61% không phải là tốt, nhưng với một mô hình sử dụng ngay, chưa tiền xử lý, thì cũng không quá tệ. Để xem thêm nhiều thước đo khác, ta có thể dùng classification report của scikit-learn:

from sklearn.metrics import classification_reporty_true, y_pred = y_test, knn_model_1.predict(X_test)print(classification_report(y_true, y_pred))
 
             precision    recall  f1-score   support      False       0.66      0.64      0.65       179       True       0.56      0.57      0.57       141avg / total       0.61      0.61      0.61       320

Bây giờ chúng ta sẽ giới thiệu chuẩn hóa (scaling) và đưa về trung tâm (centering), những phương pháp cơ bản nhất để tiền xử lý dữ liệu số, và xem liệu chúng ảnh hưởng đến hiệu năng mô hình như thế nào.

Cơ chế của Tiền xử lý: Chuẩn hóa và Đưa về trung tâm

Trước khi chạy một mô hình, như hồi quy (dự đoán biến liên tục) hay phân loại (dự đoán biến rời rạc), bạn hầu như luôn muốn thực hiện một số tiền xử lý. Với các biến số, phổ biến là bạn sẽ chuẩn hóa về khoảng [0,1] (normalize) hoặc chuẩn hóa theo Z-score (standardize) dữ liệu. Các thuật ngữ này nghĩa là gì?

Normalize chỉ đơn giản là biến đổi dữ liệu sao cho giá trị nhỏ nhất là 0 và lớn nhất là 1. Để đạt được điều này, ta biến đổi mỗi điểm dữ liệu $x$ thành

$$x_{normalized} = \frac{x-x_{min}}{x_{max}-x_{min}}.$$

Standardize hơi khác: mục tiêu là đưa dữ liệu về trung tâm quanh 0 và chuẩn hóa theo độ lệch chuẩn:

$$x_{standardized} = \frac{x-\mu}{\sigma},$$

với $\mu$ và $\sigma$ lần lượt là trung bình và độ lệch chuẩn của tập dữ liệu. Trước hết lưu ý rằng các phép biến đổi này chỉ thay đổi khoảng giá trị chứ không thay đổi phân phối. Sau đó bạn có thể muốn dùng các biến đổi khác, như log hoặc Box-Cox, để dữ liệu trông giống phân phối Gauss hơn (hình chuông). Nhưng trước khi đi xa hơn, điều quan trọng là hỏi: vì sao ta chuẩn hóa dữ liệu? Khi nào thì phù hợp hơn? Ví dụ, liệu nó quan trọng hơn trong phân loại so với hồi quy không?

Hãy đào sâu vào các bài toán phân loại trước và xem việc chuẩn hóa ảnh hưởng đến hiệu năng của k-láng giềng gần nhất thế nào:

Tiền xử lý: chuẩn hóa trong thực hành

Dưới đây tôi sẽ (i) chuẩn hóa dữ liệu, (ii) dùng k-láng giềng gần nhất và (iii) kiểm tra hiệu năng mô hình. Tôi sẽ dùng hàm scale của scikit-learn, hàm này chuẩn hóa tất cả các đặc trưng (cột) trong mảng truyền vào.

from sklearn.preprocessing import scaleXs = scale(X)from sklearn.cross_validation import train_test_splitXs_train, Xs_test, y_train, y_test = train_test_split(Xs, y, test_size=0.2, random_state=42)knn_model_2 = knn.fit(Xs_train, y_train)print('k-NN score for test set: %f' % knn_model_2.score(Xs_test, y_test))print('k-NN score for training set: %f' % knn_model_2.score(Xs_train, y_train))y_true, y_pred = y_test, knn_model_2.predict(Xs_test)print(classification_report(y_true, y_pred))
 
 k-NN score for test set: 0.712500k-NN score for training set: 0.814699             precision    recall  f1-score   support      False       0.72      0.79      0.75       179       True       0.70      0.62      0.65       141avg / total       0.71      0.71      0.71       320

Tất cả các thước đo đều cải thiện thêm 0,1, tức tăng 16% và là mức cải thiện đáng kể! Như đã gợi ý ở trên, trước khi chuẩn hóa có một số biến dự đoán có khoảng giá trị chênh lệch nhau nhiều bậc độ lớn, nghĩa là một hai biến có thể chi phối trong bối cảnh thuật toán như k-NN. Hai lý do chính để bạn chuẩn hóa dữ liệu là

  1. Các biến dự đoán của bạn có thể có khoảng giá trị khác biệt đáng kể và trong một số tình huống, như khi dùng k-NN, điều này cần được giảm thiểu để một số đặc trưng không lấn át thuật toán;
  2. Bạn muốn các đặc trưng độc lập với đơn vị đo, tức không phụ thuộc vào thang đo: ví dụ, bạn có một đặc trưng được đo bằng mét còn tôi đo bằng centimet. Nếu cả hai chúng ta đều chuẩn hóa dữ liệu của mình, đặc trưng này sẽ tương đương với nhau.

Chúng ta đã thấy vị trí thiết yếu của tiền xử lý trong quy trình khoa học dữ liệu, ở dạng chuẩn hóa và đưa về trung tâm, và qua đó thúc đẩy cách tiếp cận tổng thể cho các thách thức máy học. Trong các bài viết sau, tôi hy vọng sẽ mở rộng thảo luận sang các dạng tiền xử lý khác, như biến đổi dữ liệu số và tiền xử lý dữ liệu phân loại, cả hai đều là thành phần thiết yếu trong bộ công cụ của mọi nhà khoa học dữ liệu. Trước khi chuyển sang nội dung này, ở bài tiếp theo tôi sẽ khám phá vai trò của chuẩn hóa trong các phương pháp hồi quy cho bài toán phân loại. Cụ thể, tôi sẽ xem hồi quy logistic và bạn sẽ thấy kết quả rất khác so với những gì vừa thấy trong bối cảnh k-láng giềng gần nhất.

Trong cửa sổ tương tác dưới đây, bạn có thể tự mình thử với dữ liệu. Hãy bắt đầu bằng cách thay đổi biến n_neig, là số láng giềng dùng trong thuật toán k-NN. Bạn cũng có thể chuẩn hóa dữ liệu bằng cách đặt sc = True, nếu muốn. Sau đó chạy toàn bộ script để xem độ chính xác của mô hình, kèm theo classification report.

import pandas as pdimport matplotlib.pyplot as pltfrom sklearn.cross_validation import train_test_splitfrom sklearn import neighborsfrom sklearn.preprocessing import scalefrom sklearn.metrics import classification_report # Set the the number of neighbors for k-NNn_neig = 5# Set sc = True if you want to scale your featuressc = False# Load datadf = pd.read_csv('http://archive.ics.uci.edu/ml/machine-learning-databases/wine-quality/winequality-red.csv ' , sep = ';')X = df.drop('quality' , 1).values# drop target variable# Here we scale, if desiredif sc == True: X = scale(X)# Target valuey1 = df['quality'].values# original target variabley = y1 <= 5# new target variable: is the rating <= 5?# Split the data into a test set and a training setX_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)# Train k-NN model and print performance on the test setknn = neighbors.KNeighborsClassifier(n_neighbors = n_neig)knn_model = knn.fit(X_train, y_train)y_true, y_pred = y_test, knn_model.predict(X_test)print('k-NN accuracy for test set: %f' % knn_model.score(X_test, y_test))print(classification_report(y_true, y_pred))

Từ điển

Học có giám sát: Nhiệm vụ suy ra biến đích từ các biến dự đoán. Ví dụ, suy ra biến đích 'có bệnh tim' từ các biến dự đoán như 'tuổi', 'giới tính' và 'tình trạng hút thuốc'.

Nhiệm vụ phân loại: Một nhiệm vụ học có giám sát là nhiệm vụ phân loại nếu biến đích gồm các hạng mục (ví dụ 'nhấp' hoặc 'không', khối u 'ác tính' hoặc 'lành tính').

Nhiệm vụ hồi quy: Một nhiệm vụ học có giám sát là nhiệm vụ hồi quy nếu biến đích là biến thay đổi liên tục (ví dụ giá nhà) hoặc biến phân loại có thứ tự như 'xếp hạng chất lượng rượu'.

k-láng giềng gần nhất: Thuật toán cho nhiệm vụ phân loại, trong đó một điểm dữ liệu được gán nhãn theo kết quả bỏ phiếu đa số của k láng giềng gần nhất của nó.

Tiền xử lý: Nhiều thao tác mà các nhà khoa học dữ liệu dùng để đưa dữ liệu về dạng phù hợp hơn với mục đích phân tích. Ví dụ, trước khi phân tích cảm xúc dữ liệu Twitter, bạn có thể loại bỏ thẻ html, khoảng trắng thừa, mở rộng chữ viết tắt và tách tweet thành danh sách các từ chứa trong đó.

Đưa về trung tâm và Chuẩn hóa: Cả hai đều là dạng tiền xử lý dữ liệu số, tức dữ liệu là con số, trái với dữ liệu phân loại hay chuỗi; đưa về trung tâm một biến nghĩa là trừ đi giá trị trung bình của biến đó khỏi mỗi điểm dữ liệu để biến mới có trung bình bằng 0; chuẩn hóa một biến nghĩa là nhân mỗi điểm dữ liệu với một hằng số để thay đổi khoảng giá trị. Xem phần nội dung bài viết để biết tầm quan trọng và ví dụ minh họa.

Bài viết này được tạo từ một Jupyter notebook. Bạn có thể tải notebook tại đây.

Chủ đề

Liên quan