Khám phá thư viện sklearn — machine learning

Viet Hung Nguyen
PyMivn
Published in
6 min readOct 19, 2017

sklearn là thư viện về machine learning phổ biến nhất của Python. Nó viết sẵn các thuật toán lằng nhằng phức tạp, bạn chỉ việc nhét dữ liệu vào, chờ nó tính toán rồi lấy kết quả, dễ như ăn kẹo.

Iris

Bài này thừa nhận rằng bạn có biết đọc code Python. Ta tập trung vào: kiến thức về xử lý dữ liệu, machine learning và sử dụng sklearn. Nếu bạn không biết cả 3 thứ này, học cả 3 cùng lúc sẽ rất mệt và không hiệu quả.

import sklearn
import sys
print("Python version: {}".format(sys.version))
print("sklearn version: {}".format(sklearn.__version__))

Kết quả

Python version: 3.5.2 (default, Nov 17 2016, 17:05:23) 
[GCC 5.4.0 20160609]
sklearn version: 0.19.0

Dữ liệu và các thuộc tính

sklearn có sẵn các bộ dữ liệu thường được dùng trong nghiên cứu. Lấy danh sách các bộ dữ liệu có sẵn trong sklearn bằng code Python

import sklearn.datasets
list_of_data_funcs = [s for s in dir(sklearn.datasets) if s.startswith('load')]
list_of_data_funcs, len(list_of_data_funcs)

Kết quả

(['load_boston',
'load_breast_cancer',
'load_diabetes',
'load_digits',
'load_files',
'load_iris',
'load_linnerud',
'load_mlcomp',
'load_sample_image',
'load_sample_images',
'load_svmlight_file',
'load_svmlight_files',
'load_wine'],
13)

Hoa Iris

Bộ dữ liệu về các giống hoa Iris, được dùng làm ví dụ với các thuật toán phân loại (classification) — dự đoán giống hoa dựa trên kích thước của hoa.

iris = sklearn.datasets.load_iris()type(iris)
# sklearn.utils.Bunch

Chi tiết về kiểu Bunch: help(sklearn.utils.Bunch)

sklearn.utils.Bunch(**kwargs)
Docstring:
Container object for datasets

Dictionary-like object that exposes its keys as attributes.

Khám phá

dir(iris)# ['DESCR', 'data', 'feature_names', 'target', 'target_names']type(iris.data)# numpy.ndarrayiris.data.shape # 150 rows (samples), 4 columns (features)# (150, 4)iris.target.shape # 150 x 1# (150,)iris.target_names# array(['setosa', 'versicolor', 'virginica'],
dtype='<U10')
iris.target# array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2])

3 giống hoa Iris

  • 0: setosa
  • 1: versicolor
  • 2: virginica
iris.feature_names# ['sepal length (cm)',
'sepal width (cm)',
'petal length (cm)',
'petal width (cm)']
iris.data[:5]# array([[ 5.1, 3.5, 1.4, 0.2],
[ 4.9, 3. , 1.4, 0.2],
[ 4.7, 3.2, 1.3, 0.2],
[ 4.6, 3.1, 1.5, 0.2],
[ 5. , 3.6, 1.4, 0.2]])

Dữ liệu có 4 thuộc tính (feature)

  • chiều dài sepal (cm)
  • chiều rộng sepal
  • chiều dài petal
  • chiều rộng petal

Mục đích bài toán

Dựa vào chiều dài và chiều rộng của sepal (đài hoa) /ˈsɛp(ə)l/ kết hợp với chiều dài và rộng của petal (cánh hoa) /ˈpɛt(ə)l/ để phân loại các giống hoa Iris.

Khám phá dữ liệu

Dữ liệu đã có sẵn, giờ chỉ cần xoay đi, xoay lại, lộn lên lộn xuống xem dữ liệu có ý nghĩa gì. Đây là bước cơ bản khi phân tích mọi thứ, và thường ta sẽ vẽ hình để nhìn cho dễ.

Một điều dễ gây “ảo tưởng” của những người học ML là ta luôn bắt đầu với bước này!!! Sự thật là:

  • không phải lúc nào cũng có sẵn dữ liệu — ta có thể phải tự thu thập dữ liệu
  • dữ liệu gần như không bao giờ sạch sẽ như ví dụ này: sẽ có thông tin bị thiếu, bị lệch về độ lớn, sai …

Nên phần “tiền xử lý” — làm sạch dữ liệu, trên thực tế, mới là phần mà người làm dữ liệu tốn nhiều thời gian. Nếu không thành thạo phần làm sạch / thu thập dữ liệu này thì chẳng có dữ liệu nào mà phân tích hay ML cả.

import matplotlib.pyplot as plt
%matplotlib inline
x_feature = 0
y_feature = 1
x_column = iris.data[:, x_feature] # lấy tất cả các dòng của cột x_feature(0)
y_column = iris.data[:, y_feature]
plt.scatter(x_column, y_column, c=iris.target)
plt.xlabel(iris.feature_names[x_feature])
plt.ylabel(iris.feature_names[y_feature])

Mọi hàm vẽ trên matplotlib đều đơn giản như thế, chỉ cần đưa vào số liệu trục x, truc y, thế là xong. Các argument khác sẽ làm thêm màu mè hay tùy chỉnh chi tiết nhưng về cơ bản chỉ có vậy.

Câu hỏi

Hình trên chỉ vẽ dữ liệu 2 chiều (2 features của sample), nếu dữ liệu có nhiều chiều thì sao?

Ở ví dụ Iris này ta có 4 features, ta không thể vẽ ra không gian 4 chiều rồi nhìn vào đó. Con người chỉ có khả năng quan sát dữ liệu 2 chiều (2D) hay 3 chiều (3D), vì vậy sẽ phải chọn ra 2 hay 3 features rồi vẽ. Việc lựa chọn này hoàn toàn phụ thuộc vào người phân tích, phụ thuộc họ muốn thấy mối liên hệ giữa những đại lượng nào.

Dữ liệu có 1000 features thì sao?

Ta có thể có hàng trăm, hay hàng nghìn số liệu để mô tả một ngôi nhà, nhưng không phải feature nào cũng có nhiều ý nghĩa đối với giá của ngôi nhà. Số phòng ngủ hay phòng vệ sinh hẳn quan trọng hơn chiều rộng và chiều cao của cửa sổ. Lựa chọn những features có quan hệ với kết quả cũng là việc của người làm phân tích. Việc này trên thực tế không quá phức tạp, nhờ những phương pháp toán học và công cụ có sẵn giúp ta chọn ra những feature (feature selecting) có ảnh hưởng nhất.

Khi sklearn đã có sẵn các thuật toán, việc còn lại của người phân tích sẽ là làm sạch dữ liệu, lựa chọn thuật toán tốt nhất, cho kết quả đúng nhất. Phân tích tỷ lệ sai là bao nhiêu? và sai thì làm sao?

99% có phải 1 độ chính xác cao khi nhận diện chữ viết? 99% nghe hẳn là rất cao! Nhưng nếu ta có 1 triệu văn bản cần nhận diện, sẽ có bao nhiêu văn bản bị sai?

10**6 - 10**6 * 99 / 100# 10000.0

10.000 văn bản bị sai. Với 10 nghìn văn bản sai, bạn sẽ phải ngồi lần lại 1 triệu văn bản để tìm ra cái nào sai… vậy cuối cùng việc 99% đúng kia có giúp ích gì? thà ta làm thủ công toàn bộ còn hơn!

Nếu Facebook.com có khả năng nhận diện khuôn mặt của bạn đúng 99% thì sao? Thì chả sao cả, nó sẽ tag đúng bạn, hoặc có tag sai 1 trong 100 bức ảnh thì bạn tự chỉnh lại cho đúng, không ai làm sao, cũng không ai mất gì.

Vậy là cùng 99%, nhưng tùy vào bài toán, yêu cầu cụ thể, mà nó mang ý nghĩa khác nhau.

Estimator

Mọi thuật toán có sẵn trong sklearn đều biểu diễn bằng một object "Estimator". Một vài thuật toán cơ bản:

  • Linear Regression: dự đoán quan hệ bằng 1 đường thẳng
  • Logistic Regression: phân nhóm bằng 1 đường thẳng
from sklearn.linear_model import LinearRegression, LogisticRegressionmodel = LinearRegression()logistic_model = LogisticRegression()

Khi đã có estimator (model) rồi, chỉ còn 2 thao tác phải làm:

  • train/fit với dữ liệu đã có, để estimator chỉnh tham số cho phù hợp với mô hình
  • predict với dữ liệu mới, để đưa ra kết quả (dự đoán giá, chia nhóm 1 nhóm 2)

Một bài toán Linear Regression đơn giản

  • 1 quả chuối — giá 2000
  • 2 quả chuối — giá 4000
  • 9 quả chuối — giá 18000

Hỏi 5 quả chuối gía bao nhiêu tiền? Cứ xem như ta không biết phép tính nhân, hãy dùng Linear Regression để giải.

Xem đầy đủ bài viết và code tại https://github.com/pymivn/math-stats-ml/blob/master/sklearn_tut1.ipynb

Hết.
HVN at http://www.familug.org/ and http://pymi.vn

Đăng ký học #Python 3 từ con số 0 tại https://pymi.vn/ — trung tâm đào tạo lập trình viên Python số 1 Việt Nam.

Nhập email vào http://invite.pymi.vn/ để nhận thư mời tham gia forum hỏi đáp Python, Django, Golang, Linux …

--

--