3Yêu cầuĐảm bảo bạn có:• Python 3.7+• Thư viện: NumPy, pandas, polars, seaborn, matplotlib, scikit-learn, lightgbm, imbalanced-learn,joblib, catboostHãy tạo một lớp tên là Pipeline chứa
Trang 1Lập trình Python cho máy học ( CS116 )
Home Credit - Credit Risk Model Stability
GVHD: Nguyễn Vũ Anh Khoa Sinh viên thực hiện: Trần Trọng Nhân - 21522924
Hoàng Quý Mùi – 21521147 Sơn Men Kâl – 21522178
Lê Đại Trình – 22521536
TP Hồ Chí Minh, Tháng 6/2024
Trang 2Mục lục
1.1 Cách đánh giá 2
2 Mô tả bộ dữ liệu : 3 3 Yêu cầu 4 4 Các phương pháp liên quan 4 4.1 Tạo pipeline cho tiền xử lý 4
4.1.1 set_table_dtypes(df) 4
4.1.2 handle_dates(df) 4
4.1.3 filter_cols(df) 4
4.2 Tạo lớp để tổng hợp các hàm chức năng 5
4.2.1 num_expr(df) 5
4.2.2 date_expr(df) 5
4.2.3 str_expr(df) 5
4.2.4 other_expr(df) 6
4.2.5 count_expr(df) 6
4.2.6 get_exprs(df) 6
4.3 Tạo hàm đọc 1 file đồng thời tiền xử lý 7
4.3.1 read_file(path, depth=None) 7
4.4 Tạo hàm đọc nhiều file đồng thời tiền xử lý 8
4.4.1 read_files(regex_path, depth=None) 8
4.5 Tạo hàm để xử lý các đặc trưng 9
4.6 Tạo hàm Dataframe thành Pandas Dataframe với các cột phân loại 9
4.6.1 Hàm to_pandas 9
4.7 Tạo hàm tối ưu hóa bộ nhớ cho Dataframe 9
4.7.1 Hàm reduce_mem_usage 9
5 Phương pháp thực hiện 10 5.1 Khởi tạo dictionary lưu trữ các bộ dataframe 10
5.2 Data preprocessing and Feautures engineering 10
5.3 Xử lý giá trị bị thiếu và loại bỏ cột dựa trên độ tương quan 13
5.4 Chuẩn bị bộ dữ liệu cho bộ kiểm thử 14
5.5 Features engineering cho bộ kiểm thử 15
5.6 Gộp bộ huấn luyện và bộ kiểm thử 15
Trang 3Lời cảm ơn
Đầu tiên, em xin được gửi lời cảm ơn đến giảng viên là thầy Nguyễn Vũ Anh Khoa đã giúp chúng
em thực hiện bài tập này Nhờ sự giúp đỡ tận tình của thầy, em đã vượt qua những khúc mắc, khó khăn trong suốt quá trình thực hiện bài tập, từ đó hoàn thành đúng tiến độ của môn học và cho ra sản phẩm chất lượng
Trong lĩnh vực tài chính tiêu dùng, việc thiếu lịch sử tín dụng có thể xuất phát từ nhiều lý do, chẳng hạn như độ tuổi còn trẻ hoặc sự ưa thích sử dụng tiền mặt Không có dữ liệu tín dụng truyền thống, những người có ít hoặc không có lịch sử tín dụng thường bị từ chối khi xin vay Các nhà cung cấp tài chính tiêu dùng cần xác định chính xác khả năng trả nợ của khách hàng, và dữ liệu đóng vai trò then chốt trong việc này Nếu khoa học dữ liệu có thể giúp dự đoán tốt hơn khả năng trả nợ của khách hàng, các khoản vay có thể trở nên dễ tiếp cận hơn đối với những người cần chúng nhất
Hiện tại, các nhà cung cấp tài chính tiêu dùng sử dụng các phương pháp thống kê và học máy để dự đoán rủi ro cho vay, được gọi là bảng điểm Trong thực tế, hành vi của khách hàng thay đổi liên tục, vì vậy mỗi bảng điểm phải được cập nhật thường xuyên, điều này tốn khá nhiều thời gian Sự ổn định của bảng điểm trong tương lai là rất quan trọng, vì một sự giảm hiệu suất đột ngột có thể dẫn đến việc cấp các khoản vay cho những khách hàng không đủ điều kiện Các nhà cung cấp khoản vay không thể phát hiện các vấn đề tiềm ẩn sớm hơn thời điểm các khoản vay đến hạn Do đó, sự ổn định của mô hình là rất cần thiết
Được thành lập vào năm 1997, Home Credit là một nhà cung cấp tài chính tiêu dùng quốc tế, tập trung vào việc cho vay có trách nhiệm, chủ yếu đối với những người có ít hoặc không có lịch sử tín dụng Home Credit mở rộng sự bao gồm tài chính cho những người chưa được ngân hàng phục vụ, tạo ra trải nghiệm vay an toàn và tích cực Cuộc thi này trên Kaggle được tổ chức nhằm cải thiện khả năng dự đoán rủi ro tín dụng, giúp các nhà cung cấp tài chính chấp nhận nhiều đơn xin vay hơn và cải thiện cuộc sống của những người thường xuyên bị từ chối vì thiếu lịch sử tín dụng
Trong cuộc thi "Home Credit - Credit Risk Model Stability" trên Kaggle, cách đánh giá các mô hình dự đoán rủi ro tín dụng được thực hiện thông qua các bước cụ thể và sử dụng các tiêu chí sau:
• Điểm số ROC AUC: Điểm số chính được sử dụng để đánh giá các mô hình là ROC AUC (Receiver Operating Characteristic Area Under the Curve) ROC AUC là một thước đo độ hiệu quả của mô hình trong việc phân biệt giữa các khách hàng có khả năng trả nợ và không trả nợ Điểm số ROC AUC dao động từ 0 đến 1, trong đó 1 là mô hình hoàn hảo và 0.5 tương đương với việc dự đoán ngẫu nhiên
• Sự ổn định của mô hình: Bên cạnh ROC AUC, một yếu tố quan trọng khác là sự ổn định của mô hình theo thời gian Mô hình phải duy trì được hiệu suất của mình trên các tập dữ liệu khác nhau, đặc biệt là khi hành vi của khách hàng thay đổi Để đánh giá sự ổn định, các mô hình sẽ được kiểm tra trên nhiều tập dữ liệu được chia theo thời gian hoặc theo các nhóm khách hàng khác nhau
• Quy trình đánh giá chéo (Cross-Validation): Để đảm bảo mô hình không bị overfitting (quá khớp) với tập dữ liệu huấn luyện, Kaggle sử dụng quy trình đánh giá chéo Các tập dữ liệu được chia
Trang 4thành nhiều phần, và mô hình sẽ được huấn luyện và kiểm tra trên các phần khác nhau để đảm bảo tính tổng quát hóa của mô hình
• Xử lý dữ liệu thiếu và ngoại lệ: Một phần quan trọng của đánh giá mô hình là khả năng xử lý các
dữ liệu thiếu và các giá trị ngoại lệ Mô hình phải có khả năng dự đoán chính xác ngay cả khi dữ liệu không đầy đủ hoặc có những giá trị bất thường
• Hiệu quả thực tế: Cuối cùng, mô hình cũng được đánh giá dựa trên hiệu quả thực tế khi áp dụng trong các tình huống thực tế Điều này bao gồm khả năng triển khai dễ dàng, tính khả dụng và khả năng duy trì hiệu suất cao trong môi trường thực tế
Thông qua các tiêu chí đánh giá trên, cuộc thi nhằm tìm ra những mô hình không chỉ chính xác mà còn
ổn định và khả thi trong việc ứng dụng thực tế, giúp các nhà cung cấp tài chính tiêu dùng có thể chấp nhận nhiều đơn vay hơn và mở rộng sự bao gồm tài chính
1 Thông tin kinh tế và việc làm
• Thu nhập hàng năm: Phân tích phân phối thu nhập, xem xét ảnh hưởng của mức thu nhập đến khả năng trả nợ
• Nghề nghiệp: Phân loại nghề nghiệp và đánh giá mức độ rủi ro của các nhóm nghề nghiệp khác nhau
• Thời gian làm việc: Xem xét thời gian làm việc tại công ty hiện tại và mối quan hệ với khả năng trả nợ
2 Lịch sử tín dụng
• Số lượng khoản vay trước đó: Kiểm tra xem khách hàng đã từng vay bao nhiêu lần và khả năng trả nợ của họ trong quá khứ
• Tình trạng các khoản vay trước: Phân tích tình trạng của các khoản vay trước (đã trả xong, đang trả, quá hạn) và ảnh hưởng của chúng đến rủi ro tín dụng hiện tại
• Mức dư nợ hiện tại: Đánh giá mức dư nợ hiện tại và khả năng trả nợ
3 Thông tin tài sản
• Giá trị tài sản: Phân tích giá trị tài sản của khách hàng và mối quan hệ với khả năng trả nợ
• Loại tài sản: Phân loại các loại tài sản và đánh giá rủi ro tín dụng dựa trên loại tài sản mà khách hàng sở hữu
4 Thông tin khác
• Số lượng người phụ thuộc: Phân tích số lượng người phụ thuộc trong gia đình và ảnh hưởng của nó đến khả năng trả nợ
• Mục đích vay vốn: Đánh giá các mục đích vay vốn khác nhau và mức độ rủi ro tương ứng
Trang 53 Yêu cầu
Đảm bảo bạn có:
• Python 3.7+
• Thư viện: NumPy, pandas, polars, seaborn, matplotlib, scikit-learn, lightgbm, imbalanced-learn, joblib, catboost
Hãy tạo một lớp tên là Pipeline chứa các phương thức để tiền xử lý dữ liệu bằng cách sử dụng Pandas
và Pipelines
4.1.1 set_table_dtypes(df)
Phương thức này duyệt qua từng cột trong DataFrame (df) và chuyển đổi kiểu dữ liệu dựa trên các điều kiện nhất định:
• Nếu tên cột là một trong {"case_id", "WEEK_NUM", "num_group1", "num_group2"}, nó chuyển đổi cột sang kiểu Int64
• Nếu tên cột là "date_decision", nó chuyển đổi cột sang kiểu Date
• Nếu ký tự cuối cùng của tên cột là "P" hoặc "A", nó chuyển đổi cột sang kiểu Float64
• Nếu ký tự cuối cùng của tên cột là "M", nó chuyển đổi cột sang kiểu String
• Nếu ký tự cuối cùng của tên cột là "D", nó chuyển đổi cột sang kiểu Date
• Cuối cùng, nó trả về DataFrame với các kiểu dữ liệu đã được chuyển đổi
4.1.2 handle_dates(df)
Phương thức này nhằm xử lý các cột ngày tháng trong DataFrame:
• Nó duyệt qua từng cột, và nếu ký tự cuối cùng của tên cột là "D", nó thực hiện một số thao tác
• Nó trừ các giá trị ngày trong cột hiện tại từ các giá trị trong cột "date_decision"
• Sau đó, nó tính tổng số ngày giữa hai ngày
• Sau khi xử lý, nó loại bỏ các cột "date_decision" và "MONTH" khỏi DataFrame
• Cuối cùng, nó trả về DataFrame đã được sửa đổi
4.1.3 filter_cols(df)
Phương thức này lọc ra các cột dựa trên các điều kiện nhất định:
• Nó duyệt qua từng cột và kiểm tra xem tên cột không phải là {"target", "case_id",
"WEEK_NUM"} và nếu loại cột là String
• Nếu số lượng giá trị duy nhất trong cột là 1 hoặc nhiều hơn 200, nó loại bỏ cột đó
Trang 6• Cuối cùng, nó trả về DataFrame đã được lọc.
Hình 1
4.2.1 num_expr(df)
Phương thức này trích xuất các đặc trưng số từ DataFrame (df):
• Nó chọn các cột có tên kết thúc bằng "P" hoặc "A", biểu thị các đo lường số học
• Đối với mỗi cột đã chọn, nó tạo một biểu thức để tính giá trị tối đa và đặt tên cho nó tương ứng
• Cuối cùng, nó trả về danh sách các biểu thức cho giá trị tối đa của các đặc trưng số
4.2.2 date_expr(df)
Phương thức này trích xuất các đặc trưng liên quan đến ngày tháng từ DataFrame (df):
• Nó chọn các cột có tên kết thúc bằng "D", biểu thị các cột ngày tháng
• Tương tự như num_expr, nó tạo các biểu thức để tính giá trị tối đa của ngày cho mỗi cột đã chọn
và đặt tên cho chúng
• Nó trả về danh sách các biểu thức cho giá trị tối đa của các đặc trưng ngày tháng
4.2.3 str_expr(df)
Phương thức này trích xuất các đặc trưng chuỗi từ DataFrame (df):
• Nó chọn các cột có tên kết thúc bằng "M", biểu thị các cột loại chuỗi
• Nó tạo các biểu thức để tính giá trị tối đa của chuỗi cho mỗi cột đã chọn và đặt tên cho chúng tương ứng
• Trả về danh sách các biểu thức cho giá trị tối đa của các đặc trưng chuỗi
Trang 74.2.4 other_expr(df)
Phương thức này trích xuất các đặc trưng khác từ DataFrame (df):
• Nó chọn các cột có tên kết thúc bằng "T" hoặc "L"
• Tương tự như các phương thức trước, nó tính giá trị tối đa cho mỗi cột đã chọn và đặt tên cho chúng
• Trả về danh sách các biểu thức cho giá trị tối đa của các đặc trưng khác
4.2.5 count_expr(df)
Phương thức này trích xuất các đặc trưng liên quan đến đếm từ DataFrame (df):
• Nó chọn các cột chứa "num_group" trong tên của chúng
• Nó tính giá trị tối đa cho mỗi cột đã chọn và đặt tên cho chúng tương ứng
• Trả về danh sách các biểu thức cho giá trị tối đa của các đặc trưng đếm
4.2.6 get_exprs(df)
Phương thức này tập hợp tất cả các biểu thức từ các phương thức trước để có danh sách toàn diện các biểu thức trích xuất đặc trưng:
• Nó gọi tất cả các phương thức trích xuất đặc trưng riêng lẻ và nối danh sách kết quả
• Trả về danh sách hợp nhất các biểu thức cho tất cả các loại đặc trưng
class Aggregator:
#Please add or subtract features yourself, be aware that too many features will take up too much space
def num_expr(df):
cols = [col for col in df.columns if col[-1] in ("P", "A")]
expr_max = [pl.max(col).alias(f"max_{col}") for col in cols]
return expr_max
def date_expr(df):
cols = [col for col in df.columns if col[-1] in ("D")]
expr_max = [pl.max(col).alias(f"max_{col}") for col in cols]
return expr_max
def str_expr(df):
cols = [col for col in df.columns if col[-1] in ("M",)]
expr_max = [pl.max(col).alias(f"max_{col}") for col in cols]
return expr_max
def other_expr(df):
cols = [col for col in df.columns if col[-1] in ("T", "L")]
expr_max = [pl.max(col).alias(f"max_{col}") for col in cols]
return expr_max
def count_expr(df):
cols = [col for col in df.columns if "num_group" in col]
Trang 8expr_max = [pl.max(col).alias(f"max_{col}") for col in cols]
return expr_max
def get_exprs(df):
exprs = Aggregator.num_expr(df) + \
Aggregator.date_expr(df) + \ Aggregator.str_expr(df) + \ Aggregator.other_expr(df) + \ Aggregator.count_expr(df)
return exprs
Hàm read_file(path, depth=None) đọc một tệp Parquet tại đường dẫn cho trước, thực hiện tiền xử
lý dữ liệu bằng lớp Pipeline, và tùy chọn tập hợp các đặc trưng dựa trên tham số độ sâu bằng lớp Aggregator
4.3.1 read_file(path, depth=None)
• Đầu vào:
– path: Đường dẫn tới tệp Parquet
– depth: Một tham số tùy chọn chỉ độ sâu của việc tập hợp đặc trưng Mặc định là None
• Đầu ra: Trả về một DataFrame đã được xử lý
• Quá trình:
– Đọc tệp Parquet tại đường dẫn cho trước bằng cách sử dụng pl.read_parquet(path) – Thực hiện tiền xử lý dữ liệu bằng lớp Pipeline bằng cách áp dụng phương thức set_table_dtypes để đảm bảo các kiểu dữ liệu đúng
– Nếu depth được cung cấp và là 1 hoặc 2:
∗ Nhóm DataFrame theo "case_id"
∗ Tập hợp các đặc trưng dựa trên độ sâu bằng cách sử dụng lớp Aggregator và phương thức get_exprs
– Trả về DataFrame đã được xử lý
def read_file(path, depth=None):
df = pl.read_parquet(path)
df = df.pipe(Pipeline.set_table_dtypes)
if depth in [1,2]:
df = df.group_by("case_id").agg(Aggregator.get_exprs(df))
return df
Trang 94.4 Tạo hàm đọc nhiều file đồng thời tiền xử lý
Hãy tạo một hàm read_files(regex_path, depth=None) để đọc nhiều tệp Parquet khớp với mẫu biểu thức chính quy được chỉ định, thực hiện tiền xử lý dữ liệu bằng lớp Pipeline, tùy chọn tập hợp các đặc trưng dựa trên tham số độ sâu bằng lớp Aggregator, và nối kết quả
4.4.1 read_files(regex_path, depth=None)
• Đầu vào:
– regex_path: Mẫu biểu thức chính quy để khớp các đường dẫn tệp
– depth: Một tham số tùy chọn chỉ độ sâu của việc tập hợp đặc trưng Mặc định là None
• Đầu ra: Trả về một DataFrame đã được nối và xử lý
• Quá trình:
– Khởi tạo danh sách rỗng chunks để lưu trữ các DataFrame đã được xử lý
– Duyệt qua từng đường dẫn tệp khớp với mẫu biểu thức chính quy đã cung cấp bằng cách sử dụng glob(str(regex_path))
– Đọc mỗi tệp Parquet bằng cách sử dụng pl.read_parquet(path)
– Thực hiện tiền xử lý dữ liệu bằng lớp Pipeline bằng cách áp dụng phương thức set_table_dtypes
– Nếu depth được cung cấp và là 1 hoặc 2:
∗ Nhóm DataFrame theo "case_id"
∗ Tập hợp các đặc trưng dựa trên độ sâu bằng cách sử dụng lớp Aggregator và phương thức get_exprs
– Thêm DataFrame đã được xử lý vào danh sách chunks
– Nối tất cả các DataFrame trong chunks theo chiều dọc bằng cách sử dụng pl.concat(chunks, how="vertical_relaxed")
– Loại bỏ các hàng trùng lặp dựa trên cột "case_id" bằng cách sử dụng df.unique(subset=["case_id"])
– Trả về DataFrame đã được nối và xử lý
def read_files(regex_path, depth=None):
chunks = []
for path in glob(str(regex_path)):
df = pl.read_parquet(path)
df = df.pipe(Pipeline.set_table_dtypes)
if depth in [1, 2]:
df = df.group_by("case_id").agg(Aggregator.get_exprs(df))
chunks.append(df)
df = pl.concat(chunks, how="vertical_relaxed")
df = df.unique(subset=["case_id"])
return df
Trang 104.5 Tạo hàm để xử lý các đặc trưng
4.5.0.1 Đọc Dữ Liệu Dữ liệu được đọc từ các tệp Parquet, lưu trữ trong từ điển data_store Các tệp được phân thành các nhóm theo độ sâu, bao gồm depth_0, depth_1, và depth_2
4.5.0.2 Tiền Xử Lý Dữ Liệu Dữ liệu huấn luyện được xử lý qua các bước:
• Trích xuất tháng và ngày trong tuần từ cột date_decision
• Nối các DataFrame phụ vào DataFrame gốc dựa trên cột case_id
• Áp dụng các phương pháp xử lý ngày tháng từ lớp Pipeline
def feature_eng(df_base, depth_0, depth_1, depth_2):
df_base = (
df_base
.with_columns(
month_decision = pl.col("date_decision").dt.month(),
weekday_decision = pl.col("date_decision").dt.weekday(),
)
)
for i, df in enumerate(depth_0 + depth_1 + depth_2):
df_base = df_base.join(df, how="left", on="case_id", suffix=f" {i}")
df_base = df_base.pipe(Pipeline.handle_dates)
return df_base
4.6.1 Hàm to_pandas
Chuyển đổi DataFrame từ Polars sang Pandas và chuyển đổi các cột chỉ định sang kiểu dữ liệu phân loại nếu cần thiết
def to_pandas(df_data, cat_cols=None):
df_data = df_data.to_pandas()
if cat_cols is None:
cat_cols = list(df_data.select_dtypes("object").columns)
df_data[cat_cols] = df_data[cat_cols].astype("category")
return df_data, cat_cols
4.7.1 Hàm reduce_mem_usage
Giảm sử dụng bộ nhớ bằng cách điều chỉnh kiểu dữ liệu của các cột trong DataFrame