Feature selection và extraction

Feature Selection và Feature Extraction trong Machine Learning

Feature Selection & Feature Extraction in Machine Learning

Giới thiệu

Trong quy trình phát triển mô hình Machine Learning, sau bước thu thập dữ liệu và Feature Engineering, hai kỹ thuật quan trọng tiếp theo cần được áp dụng là Feature Selection (Lựa chọn đặc trưng) và Feature Extraction (Trích xuất đặc trưng). Những kỹ thuật này giúp giảm số lượng đặc trưng, loại bỏ thông tin dư thừa, cải thiện hiệu suất mô hình, và tăng tốc quá trình huấn luyện.

Bài viết này sẽ phân tích sâu về hai kỹ thuật này, cách thức hoạt động, các phương pháp phổ biến, và khi nào nên áp dụng chúng.

1. Feature Selection (Lựa chọn đặc trưng)

1.1. Định nghĩa và mục đích

Feature Selection là quá trình lựa chọn một tập con các đặc trưng có liên quan nhất từ tập đặc trưng ban đầu, loại bỏ những đặc trưng dư thừa hoặc không liên quan. Quá trình này giữ nguyên các đặc trưng gốc, chỉ loại bỏ những đặc trưng không cần thiết.

Mục đích:

  • Giảm chiều dữ liệu (dimensionality reduction)

  • Đơn giản hóa mô hình, giảm overfitting

  • Tăng độ chính xác của mô hình

  • Giảm thời gian huấn luyện

  • Cải thiện khả năng diễn giải mô hình

1.2. Các phương pháp Feature Selection

1.2.1. Filter Methods (Phương pháp lọc)

Phương pháp này đánh giá và xếp hạng các đặc trưng dựa trên các chỉ số thống kê, không phụ thuộc vào bất kỳ thuật toán học máy nào.

Ưu điểm:

  • Nhanh và tính toán hiệu quả

  • Độc lập với mô hình, nên không bị ảnh hưởng bởi bias của mô hình

  • Phù hợp với dữ liệu kích thước lớn

Nhược điểm:

  • Không tính đến tương tác giữa các đặc trưng

  • Có thể bỏ qua các đặc trưng có ít mối tương quan riêng lẻ nhưng lại quan trọng khi kết hợp

Các kỹ thuật phổ biến:

  1. Correlation (Tương quan):

import pandas as pd
import numpy as np
import seaborn as sns
import matplotlib.pyplot as plt

# Tính ma trận tương quan
correlation_matrix = df.corr()

# Vẽ heatmap
plt.figure(figsize=(12, 10))
sns.heatmap(correlation_matrix, annot=True, cmap='coolwarm', vmin=-1, vmax=1)
plt.title('Correlation Matrix')
plt.show()

# Loại bỏ đặc trưng có tương quan cao (> 0.8)
def remove_highly_correlated_features(df, threshold=0.8):
    correlation_matrix = df.corr().abs()
    upper = correlation_matrix.where(np.triu(np.ones(correlation_matrix.shape), k=1).astype(bool))
    to_drop = [column for column in upper.columns if any(upper[column] > threshold)]
    return df.drop(to_drop, axis=1)
  1. Chi-Square Test (cho biến phân loại):

from sklearn.feature_selection import chi2, SelectKBest

# Chọn k đặc trưng tốt nhất dựa vào chi-square test
selector = SelectKBest(chi2, k=10)
X_new = selector.fit_transform(X, y)

# Lấy điểm số và p-value
scores = selector.scores_
p_values = selector.pvalues_

# Hiển thị đặc trưng quan trọng nhất
feature_names = X.columns
feature_scores = pd.DataFrame({'Feature': feature_names, 'Score': scores, 'P-value': p_values})
feature_scores = feature_scores.sort_values('Score', ascending=False)
  1. ANOVA F-value (cho biến liên tục):

from sklearn.feature_selection import f_classif, SelectKBest

# Chọn k đặc trưng tốt nhất dựa vào ANOVA F-value
selector = SelectKBest(f_classif, k=10)
X_new = selector.fit_transform(X, y)
  1. Mutual Information:

from sklearn.feature_selection import mutual_info_classif, mutual_info_regression

# Cho bài toán phân loại
mi = mutual_info_classif(X, y)
# Hoặc cho bài toán hồi quy
# mi = mutual_info_regression(X, y)

# Hiển thị điểm MI
feature_importance = pd.DataFrame({'Feature': X.columns, 'Importance': mi})
feature_importance = feature_importance.sort_values('Importance', ascending=False)
  1. Variance Threshold (Loại bỏ đặc trưng có phương sai thấp):

from sklearn.feature_selection import VarianceThreshold

# Loại bỏ đặc trưng có phương sai thấp hơn ngưỡng
selector = VarianceThreshold(threshold=0.1)  # 0.1 là ngưỡng phương sai
X_new = selector.fit_transform(X)

1.2.2. Wrapper Methods (Phương pháp bao bọc)

Phương pháp này đánh giá tập con đặc trưng bằng cách sử dụng một mô hình dự đoán cụ thể. Nó tìm kiếm tập con tối ưu bằng cách huấn luyện mô hình với các tập con khác nhau và so sánh hiệu suất.

Ưu điểm:

  • Tính đến mối tương tác giữa các đặc trưng

  • Cụ thể cho mô hình được sử dụng

  • Thường cho kết quả tốt hơn filter methods

Nhược điểm:

  • Tính toán tốn kém (phải huấn luyện mô hình nhiều lần)

  • Nguy cơ overfitting

  • Không hiệu quả với dữ liệu kích thước lớn

Các kỹ thuật phổ biến:

  1. Recursive Feature Elimination (RFE):

from sklearn.feature_selection import RFE
from sklearn.ensemble import RandomForestClassifier

# Khởi tạo mô hình
model = RandomForestClassifier(n_estimators=100, random_state=42)

# Khởi tạo RFE và chọn 10 đặc trưng tốt nhất
rfe = RFE(estimator=model, n_features_to_select=10)
X_new = rfe.fit_transform(X, y)

# Lấy ranking của các đặc trưng
feature_ranking = pd.DataFrame({
    'Feature': X.columns,
    'Ranking': rfe.ranking_,
    'Selected': rfe.support_
})
feature_ranking = feature_ranking.sort_values('Ranking')
  1. Forward Selection:

from mlxtend.feature_selection import SequentialFeatureSelector as SFS
from sklearn.linear_model import LogisticRegression

# Khởi tạo mô hình
model = LogisticRegression(random_state=42)

# Khởi tạo Forward Selection
sfs = SFS(model, 
          k_features=10, 
          forward=True, 
          floating=False, 
          scoring='accuracy',
          cv=5)

# Fit SFS
sfs.fit(X, y)

# Lấy đặc trưng được chọn
selected_features = list(sfs.k_feature_names_)
  1. Backward Elimination:

# Tương tự Forward Selection nhưng với forward=False
sfs = SFS(model, 
          k_features=10, 
          forward=False,  # Backward elimination
          floating=False, 
          scoring='accuracy',
          cv=5)
  1. Exhaustive Feature Selection:

from mlxtend.feature_selection import ExhaustiveFeatureSelector as EFS

# Thử tất cả các tổ hợp có thể
efs = EFS(model,
          min_features=1,
          max_features=5,  # Giới hạn số lượng để tránh explosion
          scoring='accuracy',
          cv=5)
efs.fit(X, y)

# Lấy tổ hợp đặc trưng tốt nhất
best_features = list(efs.best_feature_names_)

1.2.3. Embedded Methods (Phương pháp nhúng)

Phương pháp này thực hiện feature selection như một phần của quá trình huấn luyện mô hình. Các thuật toán này có cơ chế lựa chọn đặc trưng tích hợp sẵn.

Ưu điểm:

  • Tương tác với thuật toán học máy

  • Ít tính toán hơn wrapper methods

  • Tính đến tương tác giữa các đặc trưng

  • Ít nguy cơ overfitting hơn wrapper methods

Nhược điểm:

  • Cụ thể cho mô hình được sử dụng

Các kỹ thuật phổ biến:

  1. LASSO Regression (L1 Regularization):

from sklearn.linear_model import Lasso

# LASSO có xu hướng đưa các hệ số của đặc trưng ít quan trọng về 0
lasso = Lasso(alpha=0.1)
lasso.fit(X, y)

# Lấy hệ số của các đặc trưng
feature_importance = pd.DataFrame({
    'Feature': X.columns,
    'Coefficient': np.abs(lasso.coef_)
})
feature_importance = feature_importance.sort_values('Coefficient', ascending=False)

# Lọc các đặc trưng có hệ số khác 0
selected_features = feature_importance[feature_importance['Coefficient'] > 0]['Feature'].tolist()
  1. Random Forest Feature Importance:

from sklearn.ensemble import RandomForestClassifier
import matplotlib.pyplot as plt

# Huấn luyện Random Forest
rf = RandomForestClassifier(n_estimators=100, random_state=42)
rf.fit(X, y)

# Lấy feature importance
feature_importance = pd.DataFrame({
    'Feature': X.columns,
    'Importance': rf.feature_importances_
})
feature_importance = feature_importance.sort_values('Importance', ascending=False)

# Vẽ biểu đồ
plt.figure(figsize=(10, 6))
plt.barh(feature_importance['Feature'][:15], feature_importance['Importance'][:15])
plt.xlabel('Importance')
plt.ylabel('Feature')
plt.title('Random Forest Feature Importance')
plt.gca().invert_yaxis() # Đảo ngược trục y để đặc trưng quan trọng nhất ở trên cùng
plt.show()

# Chọn n đặc trưng quan trọng nhất
n = 15
selected_features = feature_importance['Feature'][:n].tolist()
  1. Gradient Boosting Feature Importance:

from sklearn.ensemble import GradientBoostingClassifier

# Huấn luyện Gradient Boosting
gb = GradientBoostingClassifier(n_estimators=100, random_state=42)
gb.fit(X, y)

# Tương tự như Random Forest
feature_importance = pd.DataFrame({
    'Feature': X.columns,
    'Importance': gb.feature_importances_
})
feature_importance = feature_importance.sort_values('Importance', ascending=False)
  1. Permutation Importance:

from sklearn.inspection import permutation_importance
from sklearn.ensemble import RandomForestClassifier

# Huấn luyện mô hình
model = RandomForestClassifier(n_estimators=100, random_state=42)
model.fit(X_train, y_train)

# Tính permutation importance
result = permutation_importance(model, X_test, y_test, n_repeats=10, random_state=42)

# Lấy mean importance
importances = result.importances_mean

# Tạo DataFrame
feature_importance = pd.DataFrame({
    'Feature': X.columns,
    'Importance': importances
})
feature_importance = feature_importance.sort_values('Importance', ascending=False)
  1. SelectFromModel:

from sklearn.feature_selection import SelectFromModel
from sklearn.ensemble import RandomForestClassifier

# Khởi tạo và huấn luyện mô hình
model = RandomForestClassifier(n_estimators=100, random_state=42)

# Sử dụng SelectFromModel để chọn đặc trưng
selector = SelectFromModel(model, threshold="median")
selector.fit(X, y)

# Lấy đặc trưng được chọn
selected_features = X.columns[selector.get_support()].tolist()
X_new = selector.transform(X)

1.3. Quy trình Feature Selection

Một quy trình tiêu chuẩn cho feature selection có thể được thực hiện như sau:

# 1. Loại bỏ đặc trưng có phương sai thấp
from sklearn.feature_selection import VarianceThreshold
selector = VarianceThreshold(threshold=0.01)
X_var = selector.fit_transform(X)

# 2. Loại bỏ đặc trưng có tương quan cao
# (Hàm đã được định nghĩa ở trên)
X_corr = remove_highly_correlated_features(X_var, threshold=0.8)

# 3. Chọn đặc trưng có mối tương quan cao với biến mục tiêu
from sklearn.feature_selection import SelectKBest, f_classif
selector = SelectKBest(f_classif, k=min(20, X_corr.shape[1]))
X_uni = selector.fit_transform(X_corr, y)

# 4. Sử dụng model-based selection
from sklearn.feature_selection import SelectFromModel
from sklearn.ensemble import RandomForestClassifier
model = RandomForestClassifier(n_estimators=100, random_state=42)
selector = SelectFromModel(model, threshold="median")
X_model = selector.fit_transform(X_uni, y)

# 5. Fine-tuning với RFE
from sklearn.feature_selection import RFE
rfe = RFE(estimator=model, n_features_to_select=10)
X_final = rfe.fit_transform(X_model, y)

2. Feature Extraction (Trích xuất đặc trưng)

2.1. Định nghĩa và mục đích

Feature Extraction là quá trình tạo ra các đặc trưng mới bằng cách kết hợp hoặc biến đổi các đặc trưng ban đầu. Khác với Feature Selection, quá trình này tạo ra các đặc trưng mới từ các đặc trưng hiện có.

Mục đích:

  • Giảm chiều dữ liệu

  • Loại bỏ multicollinearity

  • Bảo toàn thông tin

  • Phát hiện cấu trúc tiềm ẩn trong dữ liệu

2.2. Các phương pháp Feature Extraction

2.2.1. Principal Component Analysis (PCA)

PCA là một kỹ thuật giảm chiều dữ liệu phổ biến, biến đổi dữ liệu thành các thành phần chính (principal components) không tương quan với nhau.

from sklearn.decomposition import PCA
import matplotlib.pyplot as plt

# Khởi tạo PCA, giảm còn 2 thành phần chính
pca = PCA(n_components=2)
X_pca = pca.fit_transform(X_scaled)  # X_scaled là dữ liệu đã được chuẩn hóa

# Phần trăm phương sai giải thích được
explained_variance = pca.explained_variance_ratio_
print(f"Explained variance: {explained_variance}")
print(f"Total explained variance: {sum(explained_variance):.4f}")

# Vẽ biểu đồ phương sai tích lũy
plt.figure(figsize=(10, 6))
plt.plot(np.cumsum(pca.explained_variance_ratio_), marker='o')
plt.xlabel('Number of Components')
plt.ylabel('Cumulative Explained Variance')
plt.title('Explained Variance by Components')
plt.grid(True)
plt.show()

# Vẽ biểu đồ scatter plot cho 2 thành phần chính đầu tiên
plt.figure(figsize=(10, 8))
scatter = plt.scatter(X_pca[:, 0], X_pca[:, 1], c=y, cmap='viridis', alpha=0.5)
plt.xlabel('First Principal Component')
plt.ylabel('Second Principal Component')
plt.title('PCA: First Two Principal Components')
plt.colorbar(scatter)
plt.show()

# Kết quả PCA
components = pd.DataFrame(
    pca.components_,
    columns=X.columns,
    index=[f'PC{i+1}' for i in range(pca.n_components_)]
)

2.2.2. Linear Discriminant Analysis (LDA)

LDA là một kỹ thuật giảm chiều có giám sát, tìm ra sự kết hợp tuyến tính của các đặc trưng nhằm tối đa hóa sự phân tách giữa các lớp.

from sklearn.discriminant_analysis import LinearDiscriminantAnalysis

# Khởi tạo LDA
lda = LinearDiscriminantAnalysis(n_components=2)  # Số thành phần <= số lớp - 1
X_lda = lda.fit_transform(X, y)

# Vẽ biểu đồ scatter plot
plt.figure(figsize=(10, 8))
scatter = plt.scatter(X_lda[:, 0], X_lda[:, 1], c=y, cmap='viridis', alpha=0.5)
plt.xlabel('First Discriminant')
plt.ylabel('Second Discriminant')
plt.title('LDA: First Two Discriminants')
plt.colorbar(scatter)
plt.show()

2.2.3. t-SNE (t-Distributed Stochastic Neighbor Embedding)

t-SNE là một kỹ thuật giảm chiều phi tuyến tính, đặc biệt hiệu quả trong việc hiển thị cấu trúc cụm phức tạp trong dữ liệu.

from sklearn.manifold import TSNE

# Khởi tạo t-SNE
tsne = TSNE(n_components=2, random_state=42, perplexity=30, n_iter=1000)
X_tsne = tsne.fit_transform(X)

# Vẽ biểu đồ scatter plot
plt.figure(figsize=(10, 8))
scatter = plt.scatter(X_tsne[:, 0], X_tsne[:, 1], c=y, cmap='viridis', alpha=0.5)
plt.xlabel('t-SNE feature 1')
plt.ylabel('t-SNE feature 2')
plt.title('t-SNE visualization')
plt.colorbar(scatter)
plt.show()

2.2.4. UMAP (Uniform Manifold Approximation and Projection)

UMAP là một kỹ thuật giảm chiều phi tuyến tính hiện đại, nhanh hơn và thường bảo toàn cấu trúc toàn cục tốt hơn t-SNE.

import umap

# Khởi tạo UMAP
reducer = umap.UMAP(n_components=2, random_state=42)
X_umap = reducer.fit_transform(X)

# Vẽ biểu đồ scatter plot
plt.figure(figsize=(10, 8))
scatter = plt.scatter(X_umap[:, 0], X_umap[:, 1], c=y, cmap='viridis', alpha=0.5)
plt.xlabel('UMAP feature 1')
plt.ylabel('UMAP feature 2')
plt.title('UMAP visualization')
plt.colorbar(scatter)
plt.show()

2.2.5. Factor Analysis

Factor Analysis là một kỹ thuật thống kê tìm kiếm các biến tiềm ẩn (latent variables) hay "yếu tố" (factors) ảnh hưởng đến các biến quan sát được.

from sklearn.decomposition import FactorAnalysis

# Khởi tạo Factor Analysis
fa = FactorAnalysis(n_components=5, random_state=42)
X_fa = fa.fit_transform(X)

# Vẽ biểu đồ heatmap cho ma trận components
plt.figure(figsize=(12, 8))
component_df = pd.DataFrame(
    fa.components_,
    columns=X.columns,
    index=[f'Factor {i+1}' for i in range(fa.n_components)]
)
sns.heatmap(component_df, annot=True, cmap='coolwarm', fmt='.2f')
plt.title('Factor Analysis Components')
plt.show()

2.2.6. Non-negative Matrix Factorization (NMF)

NMF là một kỹ thuật phân tích dữ liệu không âm thành hai ma trận không âm, thường được sử dụng trong phân tích văn bản và hình ảnh.

from sklearn.decomposition import NMF

# Đảm bảo dữ liệu không âm
X_non_negative = np.maximum(0, X)

# Khởi tạo NMF
nmf = NMF(n_components=5, random_state=42)
X_nmf = nmf.fit_transform(X_non_negative)

# Vẽ biểu đồ heatmap cho ma trận components
plt.figure(figsize=(12, 8))
component_df = pd.DataFrame(
    nmf.components_,
    columns=X.columns,
    index=[f'Component {i+1}' for i in range(nmf.n_components)]
)
sns.heatmap(component_df, annot=True, cmap='YlGnBu', fmt='.2f')
plt.title('NMF Components')
plt.show()

2.2.7. Kernel PCA

Kernel PCA mở rộng PCA để xử lý các mối quan hệ phi tuyến tính bằng cách áp dụng kernel trick.

from sklearn.decomposition import KernelPCA

# Khởi tạo Kernel PCA
kpca = KernelPCA(n_components=2, kernel='rbf', gamma=15, random_state=42)
X_kpca = kpca.fit_transform(X)

# Vẽ biểu đồ scatter plot
plt.figure(figsize=(10, 8))
scatter = plt.scatter(X_kpca[:, 0], X_kpca[:, 1], c=y, cmap='viridis', alpha=0.5)
plt.xlabel('First Principal Component')
plt.ylabel('Second Principal Component')
plt.title('Kernel PCA with RBF Kernel')
plt.colorbar(scatter)
plt.show()

2.2.8. Autoencoders

Autoencoders là một mô hình neural network sử dụng để học cách mã hóa dữ liệu vào không gian chiều thấp hơn (encoding) và sau đó khôi phục lại dữ liệu gốc (decoding).

import tensorflow as tf
from tensorflow.keras.models import Model
from tensorflow.keras.layers import Input, Dense

# Định nghĩa kích thước của bottleneck layer
encoding_dim = 10  # Số chiều của không gian mới

# Input layer
input_layer = Input(shape=(X.shape[1],))

# Encoder
encoded = Dense(50, activation='relu')(input_layer)
encoded = Dense(encoding_dim, activation='relu')(encoded)

# Decoder
decoded = Dense(50, activation='relu')(encoded)
decoded = Dense(X.shape[1], activation='sigmoid')(decoded)

# Autoencoder model
autoencoder = Model(input_layer, decoded)

# Encoder model
encoder = Model(input_layer, encoded)

# Compile model
autoencoder.compile(optimizer='adam', loss='mean_squared_error')

# Train model
history = autoencoder.fit(
    X_scaled,  # Input data (đã scale)
    X_scaled,  # Target là chính input
    epochs=50,
    batch_size=256,
    shuffle=True,
    validation_split=0.2,
    verbose=1
)

# Extract encoded features
X_encoded = encoder.predict(X_scaled)

# Vẽ biểu đồ loss
plt.figure(figsize=(10, 6))
plt.plot(history.history['loss'], label='Training Loss')
plt.plot(history.history['val_loss'], label='Validation Loss')
plt.xlabel('Epochs')
plt.ylabel('Loss')
plt.title('Autoencoder Training and Validation Loss')
plt.legend()
plt.show()

3. So sánh Feature Selection và Feature Extraction

3.1. Khi nào sử dụng Feature Selection?

  • Interpretability: Khi cần khả năng diễn giải mô hình, Feature Selection giữ lại các đặc trưng gốc nên dễ diễn giải hơn.

  • Domain knowledge: Khi có kiến thức miền và muốn xác định các đặc trưng quan trọng.

  • High dimensionality: Khi số lượng đặc trưng rất lớn và cần loại bỏ những đặc trưng không liên quan.

  • Multicollinearity: Khi có nhiều đặc trưng tương quan cao với nhau.

  • Computational efficiency: Khi muốn giảm tài nguyên tính toán mà không làm mất thông tin quan trọng.

3.2. Khi nào sử dụng Feature Extraction?

  • Complex data: Khi dữ liệu có mối quan hệ phức tạp và phi tuyến tính.

  • Visualization: Khi cần hiển thị dữ liệu nhiều chiều trong không gian 2D hoặc 3D.

  • Noise reduction: Khi dữ liệu có nhiều nhiễu và cần trích xuất các signal chính.

  • Extreme dimensionality: Khi số lượng đặc trưng cực kỳ lớn (như trong xử lý hình ảnh, văn bản).

  • Latent features: Khi muốn tìm các đặc trưng tiềm ẩn không quan sát được trực tiếp.

3.3. Kết hợp hai phương pháp

Trong thực tế, thường sử dụng cả hai phương pháp trong quy trình:

  1. Feature Selection trước, Feature Extraction sau:

    • Loại bỏ đặc trưng không liên quan hoặc nhiễu

    • Sau đó áp dụng Feature Extraction trên tập đặc trưng đã lọc

  2. Feature Extraction trước, Feature Selection sau:

    • Trích xuất đặc trưng từ dữ liệu thô (như hình ảnh, văn bản)

    • Sau đó chọn lọc các đặc trưng trích xuất quan trọng nhất

4. Pipeline Hoàn chỉnh

Dưới đây là một ví dụ pipeline hoàn chỉnh, kết hợp cả Feature Selection và Feature Extraction:

from sklearn.pipeline import Pipeline
from sklearn.preprocessing import StandardScaler
from sklearn.feature_selection import VarianceThreshold, SelectFromModel
from sklearn.decomposition import PCA
from sklearn.ensemble import RandomForestClassifier
from sklearn.model_selection import train_test_split, GridSearchCV

# Chia dữ liệu
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

# Tạo pipeline
pipeline = Pipeline([
    # Preprocessing
    ('scaler', StandardScaler()),
    
    # Feature Selection
    ('variance_filter', VarianceThreshold(threshold=0.01)),
    ('model_selection', SelectFromModel(RandomForestClassifier(n_estimators=100, random_state=42))),
    
    # Feature Extraction
    ('pca', PCA(n_components=0.95)),  # Giữ lại 95% phương sai
    
    # Final Model
    ('classifier', RandomForestClassifier())
])

# Hyperparameter tuning
param_grid = {
    'classifier__n_estimators': [100, 200, 300],
    'classifier__max_depth': [None, 10, 20],
    'classifier__min_samples_split': [2, 5, 10]
}

# Grid search with cross-validation
grid_search = GridSearchCV(pipeline, param_grid, cv=5, scoring='accuracy', n_jobs=-1)
grid_search.fit(X_train, y_train)

# Kết quả
print(f"Best parameters: {grid_search.best_params_}")
print(f"Training accuracy: {grid_search.best_score_:.4f}")
print(f"Test accuracy: {grid_search.score(X_test, y_test):.4f}")

# Kiểm tra mô hình cuối cùng
best_model = grid_search.best_estimator_

# Số lượng đặc trưng sau mỗi bước
original_features = X_train.shape[1]
after_variance = best_model.named_steps['variance_filter'].get_support().sum()
after_model_selection = best_model.named_steps['model_selection'].get_support().sum()
after_pca = best_model.named_steps['pca'].n_components_

print(f"Original features: {original_features}")
print(f"After variance threshold: {after_variance}")
print(f"After model selection: {after_model_selection}")
print(f"After PCA: {after_pca}")

5. Best Practices

5.1. Feature Selection Best Practices

  1. Start with simple methods:

    • Bắt đầu với filter methods như correlation, variance, etc.

    • Sau đó mới áp dụng các phương pháp phức tạp hơn

  2. Cross-validation:

    • Luôn đánh giá hiệu suất của feature selection bằng cross-validation

    • Tránh data leakage: thực hiện feature selection trong cross-validation pipeline

  3. Domain knowledge:

    • Kết hợp kiến thức miền khi lựa chọn đặc trưng

    • Đôi khi các đặc trưng ít tương quan nhưng có ý nghĩa quan trọng về mặt miền

  4. Stability Selection:

    • Sử dụng stability selection để chọn đặc trưng ổn định hơn

    • Lặp lại feature selection nhiều lần với bootstrap samples

from sklearn.linear_model import LogisticRegression
from sklearn.feature_selection import SelectFromModel

# Stability Selection
n_iterations = 100
selected_count = np.zeros(X.shape[1])

for i in range(n_iterations):
    # Bootstrap sample
    indices = np.random.choice(X.shape[0], X.shape[0], replace=True)
    X_sample, y_sample = X.iloc[indices], y.iloc[indices]
    
    # Feature selection
    selector = SelectFromModel(LogisticRegression(C=1, penalty='l1', solver='liblinear'))
    selector.fit(X_sample, y_sample)
    
    # Count selections
    selected_count += selector.get_support()

# Feature selection frequency
selection_freq = selected_count / n_iterations
feature_stability = pd.DataFrame({
    'Feature': X.columns,
    'Selection Frequency': selection_freq
})
feature_stability = feature_stability.sort_values('Selection Frequency', ascending=False)

# Chọn đặc trưng có tần suất lựa chọn cao
stable_features = feature_stability[feature_stability['Selection Frequency'] > 0.5]['Feature'].tolist()

5.2. Feature Extraction Best Practices

  1. Scaling before extraction:

    • Luôn scale dữ liệu trước khi áp dụng feature extraction

    • Các phương pháp như PCA rất nhạy cảm với phạm vi giá trị

  2. Variance explained:

    • Với PCA, chọn số thành phần dựa vào % phương sai giải thích được

    • Vẽ scree plot để tìm elbow point

  3. Hyperparameter tuning:

    • Điều chỉnh tham số cho các phương pháp phức tạp như t-SNE, UMAP

    • Ví dụ: perplexity cho t-SNE, n_neighbors cho UMAP

  4. Combination of methods:

    • Kết hợp nhiều phương pháp feature extraction

    • Ví dụ: PCA trước, sau đó là t-SNE

# PCA followed by t-SNE
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import StandardScaler
from sklearn.decomposition import PCA
from sklearn.manifold import TSNE

# Pipeline
pca_tsne = Pipeline([
    ('scaler', StandardScaler()),
    ('pca', PCA(n_components=50)),  # Reduce to 50 dimensions first
    ('tsne', TSNE(n_components=2, perplexity=30, n_iter=1000, random_state=42))
])

# Apply transformation
X_transformed = pca_tsne.fit_transform(X)

# Visualize
plt.figure(figsize=(10, 8))
scatter = plt.scatter(X_transformed[:, 0], X_transformed[:, 1], c=y, cmap='viridis', alpha=0.5)
plt.xlabel('Component 1')
plt.ylabel('Component 2')
plt.title('PCA + t-SNE Visualization')
plt.colorbar(scatter)
plt.show()

6. Các công cụ và thư viện

6.1. Scikit-learn

Scikit-learn cung cấp nhiều công cụ cho cả Feature Selection và Feature Extraction:

# Feature Selection trong scikit-learn
from sklearn.feature_selection import (
    SelectKBest, chi2, f_classif, mutual_info_classif,
    SelectFromModel, RFE, RFECV, VarianceThreshold
)

# Feature Extraction trong scikit-learn
from sklearn.decomposition import (
    PCA, KernelPCA, IncrementalPCA, TruncatedSVD, 
    FactorAnalysis, NMF, LatentDirichletAllocation
)
from sklearn.discriminant_analysis import LinearDiscriminantAnalysis
from sklearn.manifold import (
    TSNE, Isomap, LocallyLinearEmbedding, 
    SpectralEmbedding, MDS
)

6.2. Feature-engine

Feature-engine là thư viện chuyên biệt cho feature selection, feature extraction và feature engineering:

# Cài đặt
# pip install feature-engine

# Feature Selection
from feature_engine.selection import (
    DropConstantFeatures,
    DropDuplicateFeatures,
    DropCorrelatedFeatures,
    SmartCorrelatedSelection,
    SelectByShuffling,
    SelectByTargetMeanPerformance,
    RecursiveFeatureElimination,
    RecursiveFeatureAddition
)

# Sử dụng ví dụ
selector = DropCorrelatedFeatures(threshold=0.8, method='pearson')
X_transformed = selector.fit_transform(X, y)

6.3. UMAP

UMAP là một thư viện hiện đại cho feature extraction:

# Cài đặt
# pip install umap-learn

import umap
import matplotlib.pyplot as plt

# UMAP với tham số tùy chỉnh
reducer = umap.UMAP(
    n_components=2,          # Số chiều output
    n_neighbors=15,          # Cân bằng giữa cấu trúc cục bộ và toàn cục
    min_dist=0.1,            # Khoảng cách tối thiểu giữa các điểm trong không gian mới
    metric='euclidean',      # Metric khoảng cách
    random_state=42
)

# Fit và transform
X_umap = reducer.fit_transform(X)

# Visualize
plt.figure(figsize=(10, 8))
plt.scatter(X_umap[:, 0], X_umap[:, 1], c=y, cmap='viridis', s=5, alpha=0.8)
plt.colorbar()
plt.title('UMAP Projection')
plt.show()

6.4. Featuretools

Featuretools tập trung vào Deep Feature Synthesis, một phương pháp tự động tạo ra các đặc trưng từ dữ liệu quan hệ:

# Cài đặt
# pip install featuretools

import featuretools as ft

# Tạo EntitySet từ DataFrame
es = ft.EntitySet(id='customer_data')
es.add_dataframe(
    dataframe_name='customers',
    dataframe=customers_df,
    index='customer_id'
)
es.add_dataframe(
    dataframe_name='transactions',
    dataframe=transactions_df,
    index='transaction_id'
)

# Thêm mối quan hệ
es.add_relationship(
    parent_dataframe_name='customers',
    parent_column='customer_id',
    child_dataframe_name='transactions',
    child_column='customer_id'
)

# Chạy Deep Feature Synthesis
features, feature_defs = ft.dfs(
    entityset=es,
    target_dataframe_name='customers',
    max_depth=2,  # Độ sâu tối đa của các đặc trưng
    features_only=False
)

# Hiển thị các đặc trưng mới
print(f"Number of features: {features.shape[1]}")
print(f"Feature names: {features.columns.tolist()[:10]}...")  # 10 đặc trưng đầu tiên

7. Kết luận

Feature Selection và Feature Extraction là hai kỹ thuật quan trọng trong quy trình phát triển mô hình Machine Learning. Mỗi kỹ thuật đều có những ưu điểm riêng và phù hợp với các tình huống khác nhau:

  • Feature Selection giữ nguyên các đặc trưng gốc, chỉ loại bỏ những đặc trưng không cần thiết, giúp tăng khả năng diễn giải mô hình.

  • Feature Extraction tạo ra các đặc trưng mới từ việc kết hợp các đặc trưng gốc, hiệu quả trong việc giảm chiều dữ liệu và xử lý các mối quan hệ phức tạp.

Trong thực tế, cả hai phương pháp thường được kết hợp sử dụng để đạt hiệu quả tốt nhất. Quy trình phát triển mô hình hiệu quả nên bắt đầu với EDA kỹ lưỡng, sau đó áp dụng feature selection và/hoặc feature extraction dựa trên đặc điểm của dữ liệu và yêu cầu của bài toán.

Last updated