Hướng dẫn Scikit-Learn: Cách cài đặt và ví dụ về Scikit-Learn

⚡ Tóm tắt thông minh

Scikit-learn là thư viện mã nguồn mở. Python Thư viện này bao gồm các bước tiền xử lý, phân loại, hồi quy, phân cụm và lựa chọn mô hình, tất cả đều được hỗ trợ bởi một giao diện ước lượng nhất quán duy nhất, giúp cho toàn bộ quy trình học máy trở nên ngắn gọn, dễ đọc và có thể tái tạo được, từ dữ liệu thô đến các dự đoán đã được chấm điểm.

  • 🔘 Cài đặt: Cả Conda và pip đều hoạt động, và phiên bản ổn định hiện tại đã bao gồm tất cả các bộ chuyển đổi được sử dụng ở đây.
  • ☑️ Bộ dữ liệu đã xử lý: Tệp dữ liệu thống kê dân số người lớn của UCI với 32,561 dòng là cơ sở cho mọi ví dụ trong hướng dẫn này.
  • Đường ống: Hàm make_column_transformer thực hiện việc điều chỉnh tỷ lệ các cột số và mã hóa one-hot các cột phân loại trong một đối tượng duy nhất.
  • 🧪 điều chỉnh: GridSearchCV quét toàn bộ lưới tham số, trong khi RandomizedSearchCV lấy mẫu và hoàn thành nhanh hơn nhiều.
  • 🛠️ Ba mô hình: Hồi quy logistic đạt điểm 0.850891, XGBoost đạt 0.873157 và mạng MLPClassifier đạt 0.821253.
  • ⚠️ Khả năng giải thích: LIME cho thấy những đặc điểm nào đã đẩy một dự đoán cụ thể về phía lớp của nó, bao gồm cả những dự đoán sai.

Hướng dẫn sử dụng Scikit-learn với các bước cài đặt và ví dụ minh họa.

Scikit-learning là gì?

Học hỏi là một nguồn mở Python thư viện cho học máyNó hỗ trợ các thuật toán đã được khẳng định như KNN, gradient boosting, random forest và SVM, và được xây dựng dựa trên nền tảng của... numpy và SciPy. Scikit-learn được sử dụng rộng rãi trong các cuộc thi Kaggle cũng như trong các công ty công nghệ nổi tiếng. Nó bao gồm các bước tiền xử lý, giảm chiều dữ liệu, phân loại, hồi quy, phân cụm và lựa chọn mô hình.

Scikit-learn có một trong những tài liệu hướng dẫn tốt nhất trong số các thư viện mã nguồn mở. Nó thậm chí còn cung cấp một biểu đồ ước lượng tương tác. Lựa chọn công cụ ước tính phù hợpCông cụ này sẽ hướng dẫn bạn từ kích thước tập dữ liệu đến danh sách rút gọn các thuật toán đáng thử.

Hình dưới đây minh họa cách thức hoạt động của Scikit-learn.

Cách Scikit-learn hoạt động trong quy trình học máy.

Scikit-learn không khó sử dụng và cho kết quả xuất sắc. Tuy nhiên, nó huấn luyện trên CPU: công việc được song song hóa trên các lõi bằng đối số n_jobs thay vì trên GPU. Chạy thuật toán học sâu với nó là khả thi nhưng hiếm khi tối ưu, đặc biệt nếu bạn đã biết cách sử dụng các thư viện khác. TensorFlow.

Cách tải xuống và cài đặt Scikit-learn

Bây giờ trong này Python Hướng dẫn Scikit-learn, bạn sẽ học cách tải xuống và cài đặt Scikit-learn:

Phương án 1: AWS

Scikit-learn có thể được sử dụng trên AWS. Một ảnh Docker đã cài đặt sẵn scikit-learn sẽ giúp tiết kiệm hoàn toàn công sức thiết lập.

Để cài đặt phiên bản dành cho nhà phát triển, hãy chạy lệnh bên dưới. Jupyter:

import sys
!{sys.executable} -m pip install git+git://github.com/scikit-learn/scikit-learn.git

Phương án 2: Mac hoặc Windows sử dụng Anaconda

Để tìm hiểu về cách cài đặt Anaconda, hãy tham khảo tài liệu sau: Hướng dẫn cách tải xuống và cài đặt TensorFlow.

Tại thời điểm viết hướng dẫn này, các nhà phát triển của scikit đã phát hành một phiên bản phát triển khắc phục các sự cố có trong phiên bản hiện tại, vì vậy các bước dưới đây sử dụng bản dựng dành cho nhà phát triển đó. Trên một máy tính mới hiện nay, phiên bản ổn định hiện tại đã bao gồm tất cả các bộ chuyển đổi được sử dụng ở đây, và pip install -U scikit-learn Là đủ.

Cách cài đặt scikit-learn với Môi trường Conda

Nếu bạn đã cài đặt scikit-learn bằng môi trường conda, hãy làm theo các bước bên dưới để cập nhật lên phiên bản 0.20.

Bước 1) Kích hoạt môi trường TensorFlow

source activate hello-tf

Bước 2) Gỡ bỏ scikit-learn bằng lệnh conda.

conda remove scikit-learn

Bước 3) Cài đặt phiên bản dành cho nhà phát triển

Cài đặt phiên bản dành cho nhà phát triển của scikit-learn cùng với các thư viện cần thiết.

conda install -c anaconda git
pip install Cython
pip install h5py
pip install git+git://github.com/scikit-learn/scikit-learn.git

LƯU Ý: Windows người dùng cần Microsoft Hình ảnh C++ 14. Bạn có thể có được nó đây.

Ví dụ về Scikit-Learn với Machine Learning

Hướng dẫn Scikit này được chia thành hai phần:

  1. Học máy với scikit-learn
  2. Cách tin cậy mô hình của bạn với LIME

Phần đầu tiên trình bày chi tiết cách xây dựng một pipeline, tạo mô hình và tinh chỉnh các siêu tham số, trong khi phần thứ hai đề cập đến việc giải thích kết quả mô hình.

Bước 1) Nhập dữ liệu

Trong bài hướng dẫn Scikit learn này, bạn sẽ sử dụng bộ dữ liệu điều tra dân số người trưởng thành.

Tệp được đọc trực tiếp từ Kho lưu trữ Học máy UCI trong đoạn mã bên dưới, vì vậy không cần tải xuống thủ công. Nếu bạn quan tâm đến số liệu thống kê mô tả, các công cụ Dive và Overview rất đáng để xem xét. Tham khảo thêm tại... hướng dẫn này Để tìm hiểu thêm về Lặn và Tổng quan.

Bạn nhập tập dữ liệu bằng pandas. Lưu ý rằng bạn cần chuyển đổi các biến liên tục sang định dạng số thực.

Tập dữ liệu này bao gồm tám biến phân loại, được liệt kê trong CATE_FEATURES:

  • lớp học nghề
  • giáo dục
  • hôn nhân
  • nghề nghiệp
  • mối quan hệ
  • cuộc đua
  • quan hệ tình dục
  • quê hương

Nó cũng bao gồm sáu biến liên tục, được liệt kê trong CONTI_FEATURES:

  • tuổi
  • fnlwgt
  • giáo dục_num
  • tăng vốn
  • vốn_lỗ
  • giờ_tuần

Các danh sách ở đây được điền thủ công để bạn có cái nhìn rõ ràng hơn về các cột đang được sử dụng. Một cách nhanh hơn để lập danh sách các cột phân loại hoặc liên tục là:

## List Categorical
CATE_FEATURES = df_train.iloc[:,:-1].select_dtypes('object').columns
print(CATE_FEATURES)

## List continuous
CONTI_FEATURES =  df_train._get_numeric_data()
print(CONTI_FEATURES)

Đây là mã để nhập dữ liệu:

# Import dataset
import pandas as pd

## Define path data
COLUMNS = ['age','workclass', 'fnlwgt', 'education', 'education_num', 'marital',
           'occupation', 'relationship', 'race', 'sex', 'capital_gain', 'capital_loss',
           'hours_week', 'native_country', 'label']
### Define continuous list
CONTI_FEATURES  = ['age', 'fnlwgt','capital_gain', 'education_num', 'capital_loss', 'hours_week']
### Define categorical list
CATE_FEATURES = ['workclass', 'education', 'marital', 'occupation', 'relationship', 'race', 'sex', 'native_country']

## Prepare the data
features = ['age','workclass', 'fnlwgt', 'education', 'education_num', 'marital',
           'occupation', 'relationship', 'race', 'sex', 'capital_gain', 'capital_loss',
           'hours_week', 'native_country']

PATH = "https://archive.ics.uci.edu/ml/machine-learning-databases/adult/adult.data"

df_train = pd.read_csv(PATH, skipinitialspace=True, names = COLUMNS, index_col=False)
df_train[CONTI_FEATURES] =df_train[CONTI_FEATURES].astype('float64')
df_train.describe()

Gọi hàm describe() trên khung sẽ trả về số liệu thống kê tóm tắt cho sáu cột liên tục:

tuổi fnlwgt giáo dục_num tăng vốn vốn_lỗ giờ_tuần
tính 32561.000000 3.256100e + 04 32561.000000 32561.000000 32561.000000 32561.000000
nghĩa là 38.581647 1.897784e + 05 10.080679 1077.648844 87.303830 40.437456
tiêu chuẩn 13.640433 1.055500e + 05 2.572720 7385.292085 402.960219 12.347429
phút 17.000000 1.228500e + 04 1.000000 0.000000 0.000000 1.000000
25% 28.000000 1.178270e + 05 9.000000 0.000000 0.000000 40.000000
50% 37.000000 1.783560e + 05 10.000000 0.000000 0.000000 40.000000
75% 48.000000 2.370510e + 05 12.000000 0.000000 0.000000 45.000000
tối đa 90.000000 1.484705e + 06 16.000000 99999.000000 4356.000000 99.000000

Bạn có thể kiểm tra số lượng giá trị duy nhất của thuộc tính native_country. Chỉ có một hộ gia đình đến từ Hà Lan. Hộ gia đình đó không cung cấp thông tin nào và sẽ gây ra lỗi trong quá trình huấn luyện.

df_train.native_country.value_counts()
United-States                 29170
Mexico                          643
?                               583
Philippines                     198
Germany                         137
Canada                          121
Puerto-Rico                     114
El-Salvador                     106
India                           100
Cuba                             95
England                          90
Jamaica                          81
South                            80
China                            75
Italy                            73
Dominican-Republic               70
Vietnam                          67
Guatemala                        64
Japan                            62
Poland                           60
Columbia                         59
Taiwan                           51
Haiti                            44
Iran                             43
Portugal                         37
Nicaragua                        34
Peru                             31
France                           29
Greece                           29
Ecuador                          28
Ireland                          24
Hong                             20
Cambodia                         19
Trinadad&Tobago                  19
Thailand                         18
Laos                             18
Yugoslavia                       16
Outlying-US(Guam-USVI-etc)       14
Honduras                         13
Hungary                          13
Scotland                         12
Holand-Netherlands                1
Name: native_country, dtype: int64

Bạn có thể loại bỏ hàng không chứa thông tin này khỏi tập dữ liệu:

## Drop Netherland, because only one row
df_train = df_train[df_train.native_country != "Holand-Netherlands"]

Tiếp theo, bạn lưu trữ vị trí của các đối tượng liên tục trong danh sách. Bạn sẽ cần nó trong bước tiếp theo để xây dựng quy trình.

Đoạn mã bên dưới sẽ lặp qua tất cả các tên cột trong CONTI_FEATURES, đọc từng vị trí (tức là số thứ tự cột) và thêm nó vào một danh sách có tên là conti_features.

## Get the column index of the categorical features
conti_features = []
for i in CONTI_FEATURES:
    position = df_train.columns.get_loc(i)
    conti_features.append(position)
print(conti_features)  
[0, 2, 10, 4, 11, 12]

Khối lệnh tiếp theo thực hiện công việc tương tự đối với các biến phân loại.

## Get the column index of the categorical features
categorical_features = []
for i in CATE_FEATURES:
    position = df_train.columns.get_loc(i)
    categorical_features.append(position)
print(categorical_features)  
[1, 3, 5, 6, 7, 8, 9, 13]

Bây giờ hãy xem xét chính tập dữ liệu. Mỗi đặc trưng phân loại là một chuỗi ký tự, và mô hình không thể nhận giá trị chuỗi ký tự, vì vậy tập dữ liệu phải được biến đổi bằng các biến giả.

df_train.head(5)

Thực tế, bạn cần một cột cho mỗi nhóm trong mỗi thuộc tính. Trước tiên, hãy chạy đoạn mã bên dưới để tính tổng số cột cần thiết.

print(df_train[CATE_FEATURES].nunique(),
      'There are',sum(df_train[CATE_FEATURES].nunique()), 'groups in the whole dataset')
workclass          9
education         16
marital            7
occupation        15
relationship       6
race               5
sex                2
native_country    41
dtype: int64 There are 101 groups in the whole dataset

Toàn bộ tập dữ liệu chứa 101 nhóm, như đã hiển thị ở trên. Riêng đặc trưng "workclass" đã có chín nhóm. Bạn có thể liệt kê tên các nhóm bằng đoạn mã bên dưới; hàm `unique()` trả về các giá trị khác nhau của mỗi đặc trưng phân loại.

for i in CATE_FEATURES:
    print(df_train[i].unique())
['State-gov' 'Self-emp-not-inc' 'Private' 'Federal-gov' 'Local-gov' '?'
 'Self-emp-inc' 'Without-pay' 'Never-worked']
['Bachelors' 'HS-grad' '11th' 'Masters' '9th' 'Some-college' 'Assoc-acdm'
 'Assoc-voc' '7th-8th' 'Doctorate' 'Prof-school' '5th-6th' '10th'
 '1st-4th' 'Preschool' '12th']
['Never-married' 'Married-civ-spouse' 'Divorced' 'Married-spouse-absent'
 'Separated' 'Married-AF-spouse' 'Widowed']
['Adm-clerical' 'Exec-managerial' 'Handlers-cleaners' 'Prof-specialty'
 'Other-service' 'Sales' 'Craft-repair' 'Transport-moving'
 'Farming-fishing' 'Machine-op-inspct' 'Tech-support' '?'
 'Protective-serv' 'Armed-Forces' 'Priv-house-serv']
['Not-in-family' 'Husband' 'Wife' 'Own-child' 'Unmarried' 'Other-relative']
['White' 'Black' 'Asian-Pac-Islander' 'Amer-Indian-Eskimo' 'Other']
['Male' 'Female']
['United-States' 'Cuba' 'Jamaica' 'India' '?' 'Mexico' 'South'
 'Puerto-Rico' 'Honduras' 'England' 'Canada' 'Germany' 'Iran'
 'Philippines' 'Italy' 'Poland' 'Columbia' 'Cambodia' 'Thailand' 'Ecuador'
 'Laos' 'Taiwan' 'Haiti' 'Portugal' 'Dominican-Republic' 'El-Salvador'
 'France' 'Guatemala' 'China' 'Japan' 'Yugoslavia' 'Peru'
 'Outlying-US(Guam-USVI-etc)' 'Scotland' 'Trinadad&Tobago' 'Greece'
 'Nicaragua' 'Vietnam' 'Hong' 'Ireland' 'Hungary']

Do đó, tập dữ liệu huấn luyện sẽ chứa 101 + 6 cột: các nhóm one-hot cộng với sáu đặc trưng liên tục.

Scikit-learn có thể thực hiện việc chuyển đổi này theo hai bước:

  1. Chuyển đổi chuỗi ký tự thành ID. "State-gov" trở thành ID 1, "Self-emp-not-inc" trở thành ID 2, v.v. LabelEncoder sẽ thực hiện việc này cho bạn.
  2. Chuyển vị mỗi ID vào một cột mới. Tập dữ liệu có 101 ID nhóm, vì vậy sẽ có 101 cột thể hiện mọi nhóm đặc trưng phân loại. Scikit-learn cung cấp OneHotEncoder cho thao tác này.

Bước 2) Tạo tập huấn luyện/kiểm tra

Bây giờ tập dữ liệu đã sẵn sàng, hãy chia nó theo tỷ lệ 80/20: 80% cho tập huấn luyện và 20% cho tập kiểm tra.

Bạn có thể sử dụng `train_test_split`. Tham số đầu tiên là dataframe chứa các đặc trưng và tham số thứ hai là nhãn. Bạn thiết lập kích thước của tập dữ liệu kiểm tra bằng `test_size`.

from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(df_train[features],
                                                    df_train.label,
                                                    test_size = 0.2,
                                                    random_state=0)
X_train.head(5)
print(X_train.shape, X_test.shape)
(26048, 14) (6512, 14)

Bước 3) Xây dựng đường ống

Quy trình này giúp việc cung cấp dữ liệu nhất quán cho mô hình dễ dàng hơn. Ý tưởng là đẩy dữ liệu thô qua một đối tượng duy nhất thực hiện mọi thao tác theo đúng trình tự.

Với tập dữ liệu này, bạn cần chuẩn hóa các biến liên tục và chuyển đổi các biến phân loại. Bất kỳ thao tác nào cũng có thể nằm trong một quy trình tự động: các giá trị thiếu có thể được thay thế bằng giá trị trung bình hoặc trung vị, và các biến mới có thể được tạo ra.

Bạn có hai lựa chọn: mã hóa cứng hai quy trình, hoặc xây dựng một pipeline. Mã hóa cứng có thể làm rò rỉ dữ liệu thử nghiệm vào số liệu thống kê đã được hiệu chỉnh và tạo ra sự không nhất quán theo thời gian, vì vậy pipeline là lựa chọn tốt hơn.

from sklearn.preprocessing import StandardScaler, OneHotEncoder, LabelEncoder
from sklearn.compose import ColumnTransformer, make_column_transformer
from sklearn.pipeline import make_pipeline
from sklearn.linear_model import LogisticRegression

Quy trình này thực hiện hai thao tác trước khi đưa dữ liệu vào bộ phân loại logistic:

  1. Chuẩn hóa biến: StandardScaler()
  2. Chuyển đổi các tính năng phân loại: OneHotEncode(sparse=False)

Bạn thực hiện cả hai bước với hàm make_column_transformer. Khi hướng dẫn này được viết, hàm này chưa có trong phiên bản scikit-learn đã phát hành (0.19), đó là lý do tại sao phiên bản dành cho nhà phát triển được sử dụng; nó đã được tích hợp trong mọi phiên bản ổn định kể từ 0.20.

Hàm `make_column_transformer` khá đơn giản: bạn chỉ cần khai báo các cột cần biến đổi và phép biến đổi cần áp dụng. Để chuẩn hóa các đặc trưng liên tục, bạn truyền vào các tham số sau:

  • conti_features, StandardScaler() bên trong make_column_transformer
    • conti_features: danh sách các cột liên tục
    • StandardScaler: chuẩn hóa các cột đó

Đối tượng OneHotEncoder bên trong hàm make_column_transformer tự động mã hóa các nhãn.

preprocess = make_column_transformer(
    (conti_features, StandardScaler()),
    ### Need to be numeric not string to specify columns name 
    (categorical_features, OneHotEncoder(sparse=False))
)

Ghi chú phiên bản: Hai đối số trong khối trên đã được chuyển tiếp. Các bản phát hành hiện tại mong đợi máy biến áp được xử lý trước và các cột được xử lý sau, và thưa thớt đã được đổi tên đầu ra thưa thớt Trong scikit-learn 1.2 và đã bị loại bỏ trong phiên bản 1.4, vì vậy mã nguồn mới hơn có nội dung như sau: OneHotEncoder(sparse_output=False).

Bạn có thể kiểm tra xem pipeline có hoạt động hay không bằng cách sử dụng fit_transform. Kết quả đầu ra phải có kích thước 26048, 107.

preprocess.fit_transform(X_train).shape
(26048, 107)

Bộ chuyển đổi dữ liệu đã sẵn sàng. Bạn tạo pipeline bằng make_pipeline, và sau khi dữ liệu được chuyển đổi, bạn đưa dữ liệu đó vào mô hình hồi quy logistic.

model = make_pipeline(
    preprocess,
    LogisticRegression())

Việc huấn luyện mô hình với scikit-learn rất đơn giản: chỉ cần gọi hàm `fit` trong pipeline. Bạn có thể in độ chính xác bằng phương thức `score`.

model.fit(X_train, y_train)
print("logistic regression score: %f" % model.score(X_test, y_test))
logistic regression score: 0.850891

Cuối cùng, bạn có thể dự đoán các lớp bằng hàm predict_proba, hàm này trả về xác suất của mỗi lớp. Lưu ý rằng tổng của hai xác suất này bằng một.

model.predict_proba(X_test)
array([[0.83576663, 0.16423337],
       [0.94582765, 0.05417235],
       [0.64760587, 0.35239413],
       ...,
       [0.99639252, 0.00360748],
       [0.02072181, 0.97927819],
       [0.56781353, 0.43218647]])

Bước 4) Sử dụng quy trình của chúng tôi trong tìm kiếm dạng lưới

Việc tinh chỉnh các siêu tham số, tức là các giá trị xác định cấu trúc của mô hình, có thể rất tốn thời gian và công sức.

Một cách để đánh giá mô hình là thay đổi kích thước tập dữ liệu huấn luyện và đo lường hiệu suất, lặp lại bài tập mười lần để xem sự phân bố điểm số. Điều đó đòi hỏi rất nhiều công sức thủ công.

Thay vào đó, scikit-learn cung cấp các hàm thực hiện việc điều chỉnh tham số và kiểm định chéo cho bạn.

Xác thực chéo

Kiểm định chéo (cross-validation) nghĩa là trong quá trình huấn luyện, tập dữ liệu huấn luyện được chia thành n phần và mô hình được đánh giá n lần. Nếu cv được đặt là 10, mô hình sẽ được huấn luyện và đánh giá mười lần. Trong mỗi vòng, bộ phân loại được huấn luyện trên chín phần được chọn ngẫu nhiên và phần thứ mười được giữ lại để đánh giá.

Tìm kiếm lưới

Mỗi bộ phân loại đều có các siêu tham số cần điều chỉnh. Bạn có thể thử từng giá trị một hoặc thiết lập một lưới tham số. Tài liệu của scikit-learn liệt kê tất cả các tham số mà bộ phân loại logistic chấp nhận. Để giữ cho quá trình huấn luyện nhanh, ví dụ này chỉ điều chỉnh tham số C, tham số này kiểm soát việc điều chỉnh (regularization). Tham số này phải dương, và giá trị nhỏ sẽ gán trọng số lớn hơn cho bộ điều chỉnh.

Bạn sử dụng đối tượng GridSearchCV, đối tượng này nhận một từ điển chứa các siêu tham số cần điều chỉnh. Liệt kê từng siêu tham số theo sau là các giá trị bạn muốn thử. Để điều chỉnh C, bạn viết:

  • 'logisticregression__C': [0.001, 0.01, 0.1, 1.0] — tên tham số được đặt trước bởi tên bộ phân loại viết thường và hai dấu gạch dưới.

Mô hình sẽ thử bốn giá trị khác nhau: 0.001, 0.01, 0.1 và 1. Nó được huấn luyện với 10 fold, tức là cv=10.

from sklearn.model_selection import GridSearchCV
# Construct the parameter grid
param_grid = {
    'logisticregression__C': [0.001, 0.01,0.1, 1.0],
    }

Giờ đây, bạn có thể huấn luyện mô hình bằng GridSearchCV với các tham số grid và cv.

# Train the model
grid_clf = GridSearchCV(model,
                        param_grid,
                        cv=10,
                        iid=False)
grid_clf.fit(X_train, y_train)

Đầu ra:

GridSearchCV(cv=10, error_score='raise-deprecating',
       estimator=Pipeline(memory=None,
     steps=[('columntransformer', ColumnTransformer(n_jobs=1, remainder='drop', transformer_weights=None,
         transformers=[('standardscaler', StandardScaler(copy=True, with_mean=True, with_std=True), [0, 2, 10, 4, 11, 12]), ('onehotencoder', OneHotEncoder(categorical_features=None, categories=None,...ty='l2', random_state=None, solver='liblinear', tol=0.0001,
          verbose=0, warm_start=False))]),
       fit_params=None, iid=False, n_jobs=1,
       param_grid={'logisticregression__C': [0.001, 0.01, 0.1, 1.0]},
       pre_dispatch='2*n_jobs', refit=True, return_train_score='warn',
       scoring=None, verbose=0)

Ghi chú phiên bản: các Tôi Tham số hiển thị trong kết quả này đã bị loại bỏ trong scikit-learn 0.22 và bị xóa trong 0.24, vì vậy nó chỉ đơn giản là được loại bỏ khỏi lệnh gọi GridSearchCV trong các phiên bản hiện tại.

Để truy cập các tham số tốt nhất, bạn sử dụng best_params_.

grid_clf.best_params_

Đầu ra:

{'logisticregression__C': 1.0}

Sau khi huấn luyện mô hình với bốn giá trị điều chỉnh khác nhau, tham số tối ưu thu được là:

print("best logistic regression from grid search: %f" % grid_clf.best_estimator_.score(X_test, y_test))

hồi quy logistic tốt nhất từ ​​tìm kiếm dạng lưới: 0.850891

Để truy cập các xác suất dự đoán:

grid_clf.best_estimator_.predict_proba(X_test)
array([[0.83576677, 0.16423323],
       [0.9458291 , 0.0541709 ],
       [0.64760416, 0.35239584],
       ...,
       [0.99639224, 0.00360776],
       [0.02072033, 0.97927967],
       [0.56782222, 0.43217778]])

Mô hình XGBoost với scikit-learn

Giờ hãy thử một trong những thuật toán phân loại mạnh nhất trên thị trường. XGBoost là một cải tiến dựa trên thuật toán rừng ngẫu nhiên (random forest). Phần lý thuyết nền tảng của nó nằm ngoài phạm vi bài viết này. Python Hướng dẫn của Scikit-Graphics, nhưng hãy nhớ rằng XGBoost đã giành chiến thắng rất nhiều cuộc thi trên Kaggle. Trên một tập dữ liệu có kích thước trung bình, nó có thể hoạt động tốt như một thuật toán học sâu, hoặc thậm chí tốt hơn.

Bộ phân loại này khó huấn luyện vì nó có số lượng tham số rất lớn. Tất nhiên, bạn có thể sử dụng GridSearchCV để chọn các tham số đó cho mình.

Một lựa chọn tốt hơn ở đây là RandomizedSearchCV. GridSearchCV trở nên chậm khi lưới lớn, vì không gian tìm kiếm tăng lên với mỗi tham số được thêm vào. Thay vào đó, RandomizedSearchCV lấy mẫu ngẫu nhiên các giá trị của từng siêu tham số trong mỗi lần lặp, do đó 1,000 lần lặp sẽ đánh giá 1,000 tổ hợp. Về cơ bản, nó hoạt động tương tự như GridSearchCV.

Bạn cần nhập thư viện xgboost. Nếu thư viện chưa được cài đặt, hãy chạy lệnh pip3 install xgboost hoặc cài đặt nó từ bên trong dự án. Jupyter sổ tay với:

use import sys
!{sys.executable} -m pip install xgboost

Sau đó, nhập bộ phân loại và hai công cụ hỗ trợ tìm kiếm:

import xgboost
from sklearn.model_selection import RandomizedSearchCV
from sklearn.model_selection import StratifiedKFold

Bước tiếp theo trong Scikit này Python Hướng dẫn này nhằm mục đích chỉ định các tham số cần điều chỉnh. Tài liệu chính thức của XGBoost liệt kê tất cả các tham số đó. Vì mục đích của việc này... Python Trong hướng dẫn Sklearn, bạn chỉ chọn hai siêu tham số với hai giá trị cho mỗi siêu tham số, bởi vì XGBoost mất rất nhiều thời gian để huấn luyện và mỗi điểm lưới bổ sung sẽ làm tăng thêm thời gian chờ đợi.

params = {
        'xgbclassifier__gamma': [0.5, 1],
        'xgbclassifier__max_depth': [3, 4]
        }

Sau đó, bạn xây dựng một pipeline mới với bộ phân loại XGBoost và 600 bộ ước lượng. Tham số n_estimators có thể điều chỉnh được, và giá trị cao có thể dẫn đến hiện tượng quá khớp (overfitting). Bạn có thể thử các giá trị khác, nhưng hãy lưu ý rằng quá trình này có thể mất hàng giờ. Tất cả các tham số khác giữ nguyên giá trị mặc định.

model_xgb = make_pipeline(
    preprocess,
    xgboost.XGBClassifier(
                          n_estimators=600,
                          objective='binary:logistic',
                          silent=True,
                          nthread=1)
)

Bạn có thể cải thiện quá trình kiểm định chéo bằng thuật toán kiểm định chéo Stratified K-Folds. Ở đây chỉ sử dụng ba fold để tăng tốc độ tính toán, nhưng sẽ làm giảm chất lượng; hãy tăng số fold lên 5 hoặc 10 trên máy của bạn để có kết quả tốt hơn. Mô hình được huấn luyện qua bốn lần lặp.

skf = StratifiedKFold(n_splits=3,
                      shuffle = True,
                      random_state = 1001)

random_search = RandomizedSearchCV(model_xgb,
                                   param_distributions=params,
                                   n_iter=4,
                                   scoring='accuracy',
                                   n_jobs=4,
                                   cv=skf.split(X_train, y_train),
                                   verbose=3,
                                   random_state=1001)

Quá trình tìm kiếm ngẫu nhiên đã sẵn sàng, vì vậy bạn có thể huấn luyện mô hình.

#grid_xgb = GridSearchCV(model_xgb, params, cv=10, iid=False)
random_search.fit(X_train, y_train)
Fitting 3 folds for each of 4 candidates, totalling 12 fits
[CV] xgbclassifier__max_depth=3, xgbclassifier__gamma=0.5 ............
[CV] xgbclassifier__max_depth=3, xgbclassifier__gamma=0.5 ............
[CV] xgbclassifier__max_depth=3, xgbclassifier__gamma=0.5 ............
[CV] xgbclassifier__max_depth=4, xgbclassifier__gamma=0.5 ............
[CV]  xgbclassifier__max_depth=3, xgbclassifier__gamma=0.5, score=0.8759645283888057, total= 1.0min
[CV] xgbclassifier__max_depth=4, xgbclassifier__gamma=0.5 ............
[CV]  xgbclassifier__max_depth=3, xgbclassifier__gamma=0.5, score=0.8729701715996775, total= 1.0min
[CV]  xgbclassifier__max_depth=3, xgbclassifier__gamma=0.5, score=0.8706519235199263, total= 1.0min
[CV] xgbclassifier__max_depth=4, xgbclassifier__gamma=0.5 ............
[CV] xgbclassifier__max_depth=3, xgbclassifier__gamma=1 ..............
[CV]  xgbclassifier__max_depth=4, xgbclassifier__gamma=0.5, score=0.8735460094437406, total= 1.3min
[CV] xgbclassifier__max_depth=3, xgbclassifier__gamma=1 ..............
[CV]  xgbclassifier__max_depth=3, xgbclassifier__gamma=1, score=0.8722791661868018, total=  57.7s
[CV] xgbclassifier__max_depth=3, xgbclassifier__gamma=1 ..............
[CV]  xgbclassifier__max_depth=3, xgbclassifier__gamma=1, score=0.8753886905447426, total= 1.0min
[CV] xgbclassifier__max_depth=4, xgbclassifier__gamma=1 ..............
[CV]  xgbclassifier__max_depth=4, xgbclassifier__gamma=0.5, score=0.8697304768486523, total= 1.3min
[CV] xgbclassifier__max_depth=4, xgbclassifier__gamma=1 ..............
[CV]  xgbclassifier__max_depth=4, xgbclassifier__gamma=0.5, score=0.8740066797189912, total= 1.4min
[CV] xgbclassifier__max_depth=4, xgbclassifier__gamma=1 ..............
[CV]  xgbclassifier__max_depth=3, xgbclassifier__gamma=1, score=0.8707671043538355, total= 1.0min
[CV]  xgbclassifier__max_depth=4, xgbclassifier__gamma=1, score=0.8729701715996775, total= 1.2min
[Parallel(n_jobs=4)]: Done  10 out of  12 | elapsed:  3.6min remaining:   43.5s
[CV]  xgbclassifier__max_depth=4, xgbclassifier__gamma=1, score=0.8736611770125533, total= 1.2min
[CV]  xgbclassifier__max_depth=4, xgbclassifier__gamma=1, score=0.8692697535130154, total= 1.2min
[Parallel(n_jobs=4)]: Done  12 out of  12 | elapsed:  3.6min finished
/Users/Thomas/anaconda3/envs/hello-tf/lib/python3.6/site-packages/sklearn/model_selection/_search.py:737: DeprecationWarning: The default of the `iid` parameter will change from True to False in version 0.22 and will be removed in 0.24. This will change numeric results when test-set sizes are unequal. DeprecationWarning)
RandomizedSearchCV(cv=<generator object _BaseKFold.split at 0x1101eb830>,
          error_score='raise-deprecating',
          estimator=Pipeline(memory=None,
     steps=[('columntransformer', ColumnTransformer(n_jobs=1, remainder='drop', transformer_weights=None,
         transformers=[('standardscaler', StandardScaler(copy=True, with_mean=True, with_std=True), [0, 2, 10, 4, 11, 12]), ('onehotencoder', OneHotEncoder(categorical_features=None, categories=None,...
       reg_alpha=0, reg_lambda=1, scale_pos_weight=1, seed=None,
       silent=True, subsample=1))]),
          fit_params=None, iid='warn', n_iter=4, n_jobs=4,
          param_distributions={'xgbclassifier__gamma': [0.5, 1], 'xgbclassifier__max_depth': [3, 4]},
          pre_dispatch='2*n_jobs', random_state=1001, refit=True,
          return_train_score='warn', scoring='accuracy', verbose=3)

Như bạn thấy, XGBoost cho kết quả tốt hơn so với phương pháp hồi quy logistic trước đó.

print("Best parameter", random_search.best_params_)
print("best logistic regression from grid search: %f" % random_search.best_estimator_.score(X_test, y_test))
Best parameter {'xgbclassifier__max_depth': 3, 'xgbclassifier__gamma': 0.5}
best logistic regression from grid search: 0.873157
random_search.best_estimator_.predict(X_test)
array(['<=50K', '<=50K', '<=50K', ..., '<=50K', '>50K', '<=50K'],      dtype=object)

Tạo DNN với MLPClassifier trong scikit-learn

Cuối cùng, bạn có thể huấn luyện mạng nơ-ron bằng chính scikit-learn. Phương pháp tương tự như đối với bất kỳ bộ phân loại nào khác, và bộ ước lượng là MLPClassifier.

from sklearn.neural_network import MLPClassifier

Mạng lưới bên dưới được định nghĩa như sau:

  • Người giải quyết Adam
  • Chức năng kích hoạt ReLU
  • Alpha = 0.0001
  • Số lượng mỗi lô: 150
  • Hai lớp ẩn lần lượt có 200 và 100 nơ-ron
model_dnn = make_pipeline(
    preprocess,
    MLPClassifier(solver='adam',
                  alpha=0.0001,
                  activation='relu',
                    batch_size=150,
                    hidden_layer_sizes=(200, 100),
                    random_state=1))

Bạn có thể thay đổi số lượng lớp để cải thiện mô hình.

model_dnn.fit(X_train, y_train)
  print("DNN regression score: %f" % model_dnn.score(X_test, y_test))

Điểm hồi quy DNN: 0.821253

LIME: Hãy tin tưởng vào Mô hình của bạn

Giờ bạn đã có một mô hình tốt, điều bạn cần là một cách để tin tưởng vào nó. Các thuật toán học máy, đặc biệt là rừng ngẫu nhiên và mạng nơ-ron, được biết đến như những mô hình hộp đen: chúng hoạt động, nhưng không ai có thể thấy lý do tại sao.

Ba nhà nghiên cứu đã xây dựng một công cụ cho thấy cách máy tính đưa ra dự đoán. Bài báo của họ có tiêu đề là... “Tại sao tôi nên tin tưởng bạn?”và thuật toán mà họ công bố được gọi là Giải thích mô hình độc lập có thể diễn giải cục bộ (LIME).

Lấy một ví dụ. Đôi khi bạn không biết liệu dự đoán của máy học có đáng tin cậy hay không. Bác sĩ không thể chấp nhận chẩn đoán chỉ vì nó do máy tính đưa ra, và bạn cần biết liệu mô hình có đáng tin cậy trước khi đưa nó vào sử dụng.

Hãy tưởng tượng bạn có thể hiểu lý do tại sao bất kỳ bộ phân loại nào đưa ra dự đoán, ngay cả đối với các mô hình phức tạp như mạng nơ-ron, rừng ngẫu nhiên hoặc SVM với hạt nhân tùy ý. Việc tin tưởng vào một dự đoán trở nên dễ dàng hơn nhiều khi các lý do đằng sau nó được hiển thị rõ ràng, và việc quyết định khi nào không nên tin tưởng vào một mô hình cũng dễ dàng hơn. LIME cho bạn biết những đặc điểm nào đã thúc đẩy quyết định của bộ phân loại.

Chuẩn bị dữ liệu

Có một vài điều bạn cần thay đổi để chạy LIME. PythonĐầu tiên, hãy cài đặt Lime trong terminal bằng lệnh `pip install lime`.

Lime sử dụng đối tượng LimeTabularExplainer để xấp xỉ mô hình cục bộ. Đối tượng này yêu cầu:

  • một tập dữ liệu trong numpy định dạng
  • Tên của các tính năng: feature_names
  • Tên các lớp: class_names
  • Chỉ mục của cột của các tính năng phân loại: categorical_features
  • Tên của nhóm cho mỗi đặc trưng phân loại: categorical_names

Tạo bộ dữ liệu huấn luyện NumPy.

Bạn có thể sao chép và chuyển đổi df_train từ pandas sang NumPy rất dễ dàng.

df_train.head(5)
# Create numpy data
df_lime = df_train
df_lime.head(3)

Lấy tên lớp

Bạn có thể truy cập nhãn thông qua hàm unique(). Bạn sẽ thấy:

  • '<=50K'
  • '>50K'
# Get the class name
class_names = df_lime.label.unique()
class_names
array(['<=50K', '>50K'], dtype=object)

Lập chỉ mục các cột thuộc tính phân loại

Hãy sử dụng phương pháp bạn đã học trước đó để lấy tên của từng nhóm. Bạn mã hóa nhãn bằng LabelEncoder và lặp lại thao tác này trên mọi đặc trưng phân loại.

## 
import sklearn.preprocessing as preprocessing
categorical_names = {}
for feature in CATE_FEATURES:
    le = preprocessing.LabelEncoder()
    le.fit(df_lime[feature])
    df_lime[feature] = le.transform(df_lime[feature])
    categorical_names[feature] = le.classes_
print(categorical_names)    
{'workclass': array(['?', 'Federal-gov', 'Local-gov', 'Never-worked', 'Private',
       'Self-emp-inc', 'Self-emp-not-inc', 'State-gov', 'Without-pay'],
      dtype=object), 'education': array(['10th', '11th', '12th', '1st-4th', '5th-6th', '7th-8th', '9th',
       'Assoc-acdm', 'Assoc-voc', 'Bachelors', 'Doctorate', 'HS-grad',
       'Masters', 'Preschool', 'Prof-school', 'Some-college'],
      dtype=object), 'marital': array(['Divorced', 'Married-AF-spouse', 'Married-civ-spouse',
       'Married-spouse-absent', 'Never-married', 'Separated', 'Widowed'],
      dtype=object), 'occupation': array(['?', 'Adm-clerical', 'Armed-Forces', 'Craft-repair',
       'Exec-managerial', 'Farming-fishing', 'Handlers-cleaners',
       'Machine-op-inspct', 'Other-service', 'Priv-house-serv',
       'Prof-specialty', 'Protective-serv', 'Sales', 'Tech-support',
       'Transport-moving'], dtype=object), 'relationship': array(['Husband', 'Not-in-family', 'Other-relative', 'Own-child',
       'Unmarried', 'Wife'], dtype=object), 'race': array(['Amer-Indian-Eskimo', 'Asian-Pac-Islander', 'Black', 'Other',
       'White'], dtype=object), 'sex': array(['Female', 'Male'], dtype=object), 'native_country': array(['?', 'Cambodia', 'Canada', 'China', 'Columbia', 'Cuba',
       'Dominican-Republic', 'Ecuador', 'El-Salvador', 'England',
       'France', 'Germany', 'Greece', 'Guatemala', 'Haiti', 'Honduras',
       'Hong', 'Hungary', 'India', 'Iran', 'Ireland', 'Italy', 'Jamaica',
       'Japan', 'Laos', 'Mexico', 'Nicaragua',
       'Outlying-US(Guam-USVI-etc)', 'Peru', 'Philippines', 'Poland',
       'Portugal', 'Puerto-Rico', 'Scotland', 'South', 'Taiwan',
       'Thailand', 'Trinadad&Tobago', 'United-States', 'Vietnam',
       'Yugoslavia'], dtype=object)}

df_lime.dtypes
age               float64
workclass           int64
fnlwgt            float64
education           int64
education_num     float64
marital             int64
occupation          int64
relationship        int64
race                int64
sex                 int64
capital_gain      float64
capital_loss      float64
hours_week        float64
native_country      int64
label              object
dtype: object

Giờ đây, khi tập dữ liệu đã sẵn sàng, bạn có thể xây dựng các tập dữ liệu khác nhau được hiển thị trong các ví dụ Scikit learn bên dưới. Dữ liệu được chuyển đổi bên ngoài quy trình xử lý để tránh lỗi với LIME: tập huấn luyện được truyền cho LimeTabularExplainer phải là một mảng NumPy không chứa chuỗi ký tự, và phương pháp trên đã tạo ra một mảng như vậy.

from sklearn.model_selection import train_test_split
X_train_lime, X_test_lime, y_train_lime, y_test_lime = train_test_split(df_lime[features],
                                                    df_lime.label,
                                                    test_size = 0.2,
                                                    random_state=0)
X_train_lime.head(5)

Bạn có thể tạo pipeline với các tham số tối ưu được tìm thấy bởi XGBoost.

model_xgb = make_pipeline(
    preprocess,
    xgboost.XGBClassifier(max_depth = 3,
                          gamma = 0.5,
                          n_estimators=600,
                          objective='binary:logistic',
                          silent=True,
                          nthread=1))

model_xgb.fit(X_train_lime, y_train_lime)
/Users/Thomas/anaconda3/envs/hello-tf/lib/python3.6/site-packages/sklearn/preprocessing/_encoders.py:351: FutureWarning: The handling of integer data will change in version 0.22. Currently, the categories are determined based on the range [0, max(values)], while in the future they will be determined based on the unique values.
If you want the future behavior and silence this warning, you can specify "categories='auto'."In case you used a LabelEncoder before this OneHotEncoder to convert the categories to integers, then you can now use the OneHotEncoder directly.
  warnings.warn(msg, FutureWarning)
Pipeline(memory=None,
     steps=[('columntransformer', ColumnTransformer(n_jobs=1, remainder='drop', transformer_weights=None,
         transformers=[('standardscaler', StandardScaler(copy=True, with_mean=True, with_std=True), [0, 2, 10, 4, 11, 12]), ('onehotencoder', OneHotEncoder(categorical_features=None, categories=None,...
       reg_alpha=0, reg_lambda=1, scale_pos_weight=1, seed=None,
       silent=True, subsample=1))])

Bạn nhận được một cảnh báo. Cảnh báo giải thích rằng bạn không cần tạo bộ mã hóa nhãn trước khi thực hiện pipeline. Nếu bạn không sử dụng LIME, phương pháp từ phần đầu của hướng dẫn Học máy với Scikit-learn này là phù hợp. Nếu không, hãy giữ nguyên cách tiếp cận này: trước tiên tạo một tập dữ liệu được mã hóa, sau đó áp dụng bộ mã hóa one-hot bên trong pipeline.

print("best logistic regression from grid search: %f" % model_xgb.score(X_test_lime, y_test_lime))
best logistic regression from grid search: 0.873157
model_xgb.predict_proba(X_test_lime)
array([[7.9646105e-01, 2.0353897e-01],
       [9.5173013e-01, 4.8269872e-02],
       [7.9344827e-01, 2.0655173e-01],
       ...,
       [9.9031430e-01, 9.6856682e-03],
       [6.4581633e-04, 9.9935418e-01],
       [9.7104281e-01, 2.8957171e-02]], dtype=float32)

Trước khi sử dụng LIME, hãy tạo một mảng NumPy chứa các đặc trưng của các hàng bị phân loại sai. Bạn có thể sử dụng danh sách đó sau này để hiểu rõ hơn điều gì đã dẫn đến kết quả phân loại sai.

temp = pd.concat([X_test_lime, y_test_lime], axis= 1)
temp['predicted'] = model_xgb.predict(X_test_lime)
temp['wrong']=  temp['label'] != temp['predicted']
temp = temp.query('wrong==True').drop('wrong', axis=1)
temp= temp.sort_values(by=['label'])
temp.shape

(826, 16)

Tiếp theo, bạn tạo một hàm lambda để lấy dự đoán từ mô hình cho dữ liệu mới. Bạn sẽ cần nó ngay sau đó.

predict_fn = lambda x: model_xgb.predict_proba(x).astype(float)
X_test_lime.dtypes
age               float64
workclass           int64
fnlwgt            float64
education           int64
education_num     float64
marital             int64
occupation          int64
relationship        int64
race                int64
sex                 int64
capital_gain      float64
capital_loss      float64
hours_week        float64
native_country      int64
dtype: object
predict_fn(X_test_lime)
array([[7.96461046e-01, 2.03538969e-01],
       [9.51730132e-01, 4.82698716e-02],
       [7.93448269e-01, 2.06551731e-01],
       ...,
       [9.90314305e-01, 9.68566816e-03],
       [6.45816326e-04, 9.99354184e-01],
       [9.71042812e-01, 2.89571714e-02]])

Bạn chuyển đổi dataframe của pandas thành mảng NumPy.

X_train_lime = X_train_lime.values
X_test_lime = X_test_lime.values
X_test_lime
array([[4.00000e+01, 5.00000e+00, 1.93524e+05, ..., 0.00000e+00,
        4.00000e+01, 3.80000e+01],
       [2.70000e+01, 4.00000e+00, 2.16481e+05, ..., 0.00000e+00,
        4.00000e+01, 3.80000e+01],
       [2.50000e+01, 4.00000e+00, 2.56263e+05, ..., 0.00000e+00,
        4.00000e+01, 3.80000e+01],
       ...,
       [2.80000e+01, 6.00000e+00, 2.11032e+05, ..., 0.00000e+00,
        4.00000e+01, 2.50000e+01],
       [4.40000e+01, 4.00000e+00, 1.67005e+05, ..., 0.00000e+00,
        6.00000e+01, 3.80000e+01],
       [5.30000e+01, 4.00000e+00, 2.57940e+05, ..., 0.00000e+00,
        4.00000e+01, 3.80000e+01]])
model_xgb.predict_proba(X_test_lime)
array([[7.9646105e-01, 2.0353897e-01],
       [9.5173013e-01, 4.8269872e-02],
       [7.9344827e-01, 2.0655173e-01],
       ...,
       [9.9031430e-01, 9.6856682e-03],
       [6.4581633e-04, 9.9935418e-01],
       [9.7104281e-01, 2.8957171e-02]], dtype=float32)
print(features,
      class_names,
      categorical_features,
      categorical_names)
['age', 'workclass', 'fnlwgt', 'education', 'education_num', 'marital', 'occupation', 'relationship', 'race', 'sex', 'capital_gain', 'capital_loss', 'hours_week', 'native_country'] ['<=50K' '>50K'] [1, 3, 5, 6, 7, 8, 9, 13] {'workclass': array(['?', 'Federal-gov', 'Local-gov', 'Never-worked', 'Private',
       'Self-emp-inc', 'Self-emp-not-inc', 'State-gov', 'Without-pay'],
      dtype=object), 'education': array(['10th', '11th', '12th', '1st-4th', '5th-6th', '7th-8th', '9th',
       'Assoc-acdm', 'Assoc-voc', 'Bachelors', 'Doctorate', 'HS-grad',
       'Masters', 'Preschool', 'Prof-school', 'Some-college'],
      dtype=object), 'marital': array(['Divorced', 'Married-AF-spouse', 'Married-civ-spouse',
       'Married-spouse-absent', 'Never-married', 'Separated', 'Widowed'],
      dtype=object), 'occupation': array(['?', 'Adm-clerical', 'Armed-Forces', 'Craft-repair',
       'Exec-managerial', 'Farming-fishing', 'Handlers-cleaners',
       'Machine-op-inspct', 'Other-service', 'Priv-house-serv',
       'Prof-specialty', 'Protective-serv', 'Sales', 'Tech-support',
       'Transport-moving'], dtype=object), 'relationship': array(['Husband', 'Not-in-family', 'Other-relative', 'Own-child',
       'Unmarried', 'Wife'], dtype=object), 'race': array(['Amer-Indian-Eskimo', 'Asian-Pac-Islander', 'Black', 'Other',
       'White'], dtype=object), 'sex': array(['Female', 'Male'], dtype=object), 'native_country': array(['?', 'Cambodia', 'Canada', 'China', 'Columbia', 'Cuba',
       'Dominican-Republic', 'Ecuador', 'El-Salvador', 'England',
       'France', 'Germany', 'Greece', 'Guatemala', 'Haiti', 'Honduras',
       'Hong', 'Hungary', 'India', 'Iran', 'Ireland', 'Italy', 'Jamaica',
       'Japan', 'Laos', 'Mexico', 'Nicaragua',
       'Outlying-US(Guam-USVI-etc)', 'Peru', 'Philippines', 'Poland',
       'Portugal', 'Puerto-Rico', 'Scotland', 'South', 'Taiwan',
       'Thailand', 'Trinadad&Tobago', 'United-States', 'Vietnam',
       'Yugoslavia'], dtype=object)}
import lime
import lime.lime_tabular
### Train should be label encoded not one hot encoded
explainer = lime.lime_tabular.LimeTabularExplainer(X_train_lime ,
                                                   feature_names = features,
                                                   class_names=class_names,
                                                   categorical_features=categorical_features, 
                                                   categorical_names=categorical_names,
                                                   kernel_width=3)

Bây giờ hãy chọn ngẫu nhiên một hộ gia đình từ tập dữ liệu thử nghiệm và xem cả dự đoán lẫn cách máy tính đưa ra dự đoán đó.

import numpy as np
np.random.seed(1)
i = 100
print(y_test_lime.iloc[i])
>50K
X_test_lime[i]
array([4.20000e+01, 4.00000e+00, 1.76286e+05, 7.00000e+00, 1.20000e+01,
       2.00000e+00, 4.00000e+00, 0.00000e+00, 4.00000e+00, 1.00000e+00,
       0.00000e+00, 0.00000e+00, 4.00000e+01, 3.80000e+01])

Bạn có thể sử dụng công cụ giải thích với `explain_instance` để kiểm tra lý do đằng sau mô hình. Biểu đồ mà nó hiển thị được trình bày bên dưới.

exp = explainer.explain_instance(X_test_lime[i], predict_fn, num_features=6)
exp.show_in_notebook(show_all=False)

Biểu đồ giải thích LIME cho thấy sự đóng góp của các tính năng để dự đoán chính xác một hộ gia đình.

Hệ thống phân loại đã dự đoán chính xác hộ gia đình này: thu nhập thực sự trên 50 đô la.

Điều đầu tiên cần lưu ý là thuật toán phân loại này không thực sự chắc chắn. Nó dự đoán thu nhập trên 50 đô la với xác suất 64%, và con số 64% này chủ yếu dựa vào lợi nhuận từ đầu tư và tình trạng hôn nhân. Màu xanh lam đóng góp tiêu cực vào lớp tích cực, còn đường màu cam đóng góp tích cực.

Hệ thống phân loại tỏ ra lưỡng lự vì lợi nhuận vốn của hộ gia đình này bằng không, trong khi lợi nhuận vốn thường là một chỉ số tốt để dự đoán sự giàu có. Hộ gia đình này cũng làm việc ít hơn 40 giờ mỗi tuần. Tuổi tác, nghề nghiệp và giới tính đều đóng góp tích cực.

Nếu tình trạng hôn nhân là độc thân, bộ phân loại sẽ dự đoán mức thu nhập dưới 50 (0.64 – 0.18 = 0.46).

Bây giờ hãy thử một hộ gia đình khác, một hộ gia đình đã bị phân loại sai. Bảng giải thích cho hộ gia đình đó nằm ngay sau mã số.

temp.head(3)
temp.iloc[1,:-2]
age                  58
workclass             4
fnlwgt            68624
education            11
education_num         9
marital               2
occupation            4
relationship          0
race                  4
sex                   1
capital_gain          0
capital_loss          0
hours_week           45
native_country       38
Name: 20931, dtype: object
i = 1
print('This observation is', temp.iloc[i,-2:])
This observation is label        <=50K
predicted     >50K
Name: 20931, dtype: object
exp = explainer.explain_instance(temp.iloc[1,:-2], predict_fn, num_features=6)
exp.show_in_notebook(show_all=False)

Bảng giải thích LIME cho hộ gia đình, bộ phân loại được dán nhãn không chính xác.

Hệ thống phân loại dự đoán thu nhập dưới 50, điều này là sai. Hộ gia đình này khá bất thường: không có lãi vốn hay lỗ vốn, người đứng đầu đã ly hôn, gần 60 tuổi và có trình độ học vấn cao, tức là education_num > 12. Theo mô hình tổng thể, hệ thống phân loại xếp hộ gia đình này có thu nhập dưới 50.

Hãy tự mình trải nghiệm LIME và bạn sẽ nhận thấy rất nhiều lỗi rõ ràng từ bộ phân loại. Kho lưu trữ GitHub của tác giả thư viện có thêm tài liệu hướng dẫn về phân loại hình ảnh và văn bản.

Tài liệu tham khảo lệnh Scikit-learn

Dưới đây là danh sách các lệnh hữu ích áp dụng cho scikit-learn phiên bản 0.20 trở lên.

Nhiệm vụ Hàm hoặc lớp
Tạo tập dữ liệu huấn luyện/kiểm thử tàu_test_split
Xây dựng một đường ống
Chọn các cột và áp dụng phép biến đổi. tạo_biến_tháp_cột
Loại chuyển đổi
Tiêu chuẩn hóa Tiêu chuẩn
Thang đo tối thiểu-tối đa Bộ chia tỷ lệ tối thiểu
Chuẩn hóa Bộ chuẩn hóa
Điền các giá trị bị thiếu Đơn giản
Chuyển đổi phân loại Bộ mã hóa OneHot
Phù hợp và chuyển đổi dữ liệu fit_transform
Làm đường ống make_pipeline
Mô hình cơ bản
Hồi quy logistic Hậu cần
XGBoost Trình phân loại XGB
Mạng thần kinh Bộ phân loại MLP
Tìm kiếm lưới LướiTìm kiếmCV
Tìm kiếm ngẫu nhiên Tìm kiếm ngẫu nhiênCV

Câu Hỏi Thường Gặp

Cài đặt phiên bản ổn định hiện tại bằng lệnh `pip install -U scikit-learn` hoặc `conda install -c conda-forge scikit-learn`. Phiên bản dành cho nhà phát triển được sử dụng trong các bước trên chỉ cần thiết vào năm 2018, khi `make_column_transformer` chưa được phát hành; hiện tại nó đã có trong mọi phiên bản ổn định.

Hàm `fit` học các tham số như giá trị trung bình và độ lệch chuẩn của cột. Hàm `transform` áp dụng chúng vào dữ liệu. `fit_transform` thực hiện cả hai trong một lần gọi và chỉ nên tác động đến tập dữ liệu huấn luyện, không bao giờ tác động đến tập dữ liệu kiểm tra được giữ lại.

Việc áp dụng bộ mã hóa hoặc bộ điều chỉnh tỷ lệ trên toàn bộ tập dữ liệu cho phép số liệu thống kê từ tập dữ liệu kiểm thử được đưa vào mô hình. Một quy trình sẽ điều chỉnh lại mọi bộ chuyển đổi bên trong mỗi lần kiểm định chéo, do đó các hàng dữ liệu được giữ lại sẽ không được nhìn thấy cho đến khi chúng được chấm điểm.

Nó tự động hoàn thành các hình dạng quen thuộc: các khối ColumnTransformer, lưới tham số và các tên có dấu gạch dưới kép mà GridSearchCV mong đợi. RevHãy xem xét bất kỳ điều gì nhạy cảm với phiên bản, vì các đề xuất thường tái tạo các tên đối số cũ hơn, chẳng hạn như sparse thay vì sparse_output.

Không hoàn toàn. Các công cụ tìm kiếm tự động khám phá lưới nhanh hơn và loại bỏ các ứng viên yếu, nhưng bạn vẫn là người lựa chọn không gian tìm kiếm, chỉ số chấm điểm và phương pháp kiểm định chéo. Những quyết định đó quan trọng hơn chính thuật toán tìm kiếm.

Không. Quá trình huấn luyện chạy trên CPU và được song song hóa trên các lõi thông qua n_jobs. Một lớp API mảng thử nghiệm cho phép một số lượng hạn chế các bộ ước lượng chấp nhận mảng GPU, nhưng TensorFlow và các khung phần mềm tương tự vẫn là tùy chọn GPU.

Đúng vậy. Gọi set_output(transform=”pandas”) trên một transformer hoặc toàn bộ pipeline và kết quả sẽ giữ nguyên tên cột thay vì trả về chuỗi rỗng. numpy mảng, giúp việc kiểm tra đầu ra của ColumnTransformer trở nên dễ dàng hơn nhiều.

Truyền tham số class_weight=”balanced” cho các bộ ước lượng chấp nhận nó, lấy mẫu lại bằng thư viện hỗ trợ như imbalanced-learn, và chấm điểm bằng độ chính xác, độ thu hồi hoặc chỉ số F1 thay vì độ chính xác thông thường.

Tóm tắt bài viết này với: