Trong nền kinh tế hiện đại, tín dụng tiêu dùng, đặc biệt là qua hình thức thẻ tín dụng, đã trở thành một công cụ tài chính không thể thiếu, thúc đẩy chi tiêu, lưu thông hàng hóa và tăng trưởng kinh tế. Sự tiện lợi và linh hoạt của thẻ tín dụng đã giúp hàng triệu người tiếp cận các sản phẩm, dịch vụ một cách nhanh chóng. Tuy nhiên, song với sự phát triển mạnh mẽ này là sự gia tăng của rủi ro tín dụng là một trong những thách thức lớn nhất đối với sự ổn định của các ngân hàng và tổ chức tài chính.
Rủi ro tín dụng phát sinh khi khách hàng không có khả năng hoặc không sẵn sàng thực hiện nghĩa vụ trả nợ đúng hạn, dẫn đến các khoản nợ xấu. Nợ xấu không chỉ gây tổn thất tài chính trực tiếp cho các tổ chức cấp tín dụng mà còn ảnh hưởng tiêu cực đến chi phí vốn, lợi nhuận và sự ổn định của toàn hệ thống tài chính. Do đó, việc nhận diện, đo lường và quản lý hiệu quả rủi ro vỡ nợ là một nhiệm vụ khó khăn.
Với sự phát triển của khoa học dữ liệu, việc phân tích các bộ dữ liệu lớn đã mở ra những phương pháp tiếp cận mới để giải quyết bài toán này. Bằng cách khai thác thông tin từ dữ liệu, các tổ chức có thể xây dựng những mô hình dự báo mạnh mẽ, giúp nhận diện sớm các khách hàng có nguy cơ cao. Chính vì vậy, đề tài này được thực hiện nhằm đi sâu vào việc phân tích dữ liệu để trả lời các câu hỏi cốt lõi: Các đặc điểm nhân khẩu học như tuổi, giới tính, trình độ học vấn và tình trạng hôn nhân ảnh hưởng như thế nào đến xác suất vỡ nợ của một khách hàng? Lịch sử thanh toán trong quá khứ có phải là yếu tố dự báo quan trọng nhất cho hành vi vỡ nợ trong tương lai không? Và liệu mô hình hồi quy logistic có phải là một công cụ phân tích phù hợp và hiệu quả để giải quyết bài toán dự báo rủi ro này không? Bằng việc trả lời các câu hỏi này, nghiên cứu hướng đến việc cung cấp những luận cứ khoa học và có giá trị thực tiễn. Do đó, đề tài “Phân tích các yếu tố ảnh hưởng đến khả năng vỡ nợ thẻ tín dụng của khách hàng” được thực hiện nhằm ứng dụng mô hình hồi quy logistic và các kỹ thuật phân tích dữ liệu để làm rõ các yếu tố quyết định đến rủi ro này.
Mục tiêu tổng quát: Xây dựng mô hình dự báo khả năng vỡ nợ thẻ tín dụng của khách hàng dựa trên các đặc điểm nhân khẩu học và lịch sử giao dịch.
Mục tiêu cụ thể:
Phân tích và mô tả các đặc điểm của nhóm khách hàng vỡ nợ và không vỡ nợ trong bộ dữ liệu.
Xác định các yếu tố có ảnh hưởng ý nghĩa thống kê đến khả năng vỡ nợ của một khách hàng.
Xây dựng mô hình hồi quy logistic để lượng hóa mức độ tác động của các yếu tố trên và dự báo khả năng vỡ nợ. Đánh giá độ chính xác và hiệu quả của mô hình đã xây dựng thông qua các chỉ số đo lường.
Đối tượng nghiên cứu: Khả năng vỡ nợ (default) thẻ tín dụng của khách hàng.
Phạm vi nghiên cứu:
Về dữ liệu: Nghiên cứu sử dụng bộ dữ liệu thứ cấp “Default of Credit Card Clients” từ Kho lưu trữ Học máy của UCI, bao gồm 30.000 quan sát.
Về không gian và thời gian: Dữ liệu được thu thập về các khách hàng thẻ tín dụng tại Đài Loan trong khoảng thời gian từ tháng 4 năm 2005 đến tháng 9 năm 2005.
Nghiên cứu được thực hiện theo phương pháp định lượng. Dữ liệu sẽ được xử lý, trực quan hóa và phân tích bằng phần mềm RStudio. Thống kê mô tả được sử dụng để khám phá và khái quát các đặc điểm cơ bản của dữ liệu. Để xác định các yếu tố ảnh hưởng và xây dựng mô hình dự báo cho biến phụ thuộc định tính, kỹ thuật hồi quy logistic sẽ được áp dụng. Cuối cùng, hiệu quả của mô hình sẽ được đánh giá thông qua các chỉ số như ma trận nhầm lẫn, độ chính xác.
Chương 1. Giới thiệu đề tài: Trình bày bối cảnh và tính cấp thiết của việc nghiên cứu rủi ro tín dụng, từ đó xác lập các mục tiêu, đối tượng, phạm vi và phương pháp nghiên cứu tổng quan sẽ được thực hiện trong toàn bộ đề tài.
Chương 2. Cơ sở lý thuyết: Chương này trình bày các khái niệm nền tảng về rủi ro tín dụng và vỡ nợ, giới thiệu chi tiết về mô hình hồi quy logistic sẽ được sử dụng, và tổng quan các công trình nghiên cứu trước đây liên quan đến việc dự báo rủi ro tín dụng.
Chương 3. Phương pháp nghiên cứu: Chương này đi sâu vào phương pháp luận chi tiết, trình bày quy trình phân tích dữ liệu từ bước thu thập, mô tả và tiền xử lý. Đồng thời, chương cũng làm rõ việc xây dựng mô hình, các tiêu chí cụ thể được sử dụng để đánh giá độ chính xác của mô hình.
Chương 4. Kết quả phân tích: Đây là chương trọng tâm, trình bày toàn bộ kết quả thu được từ việc phân tích dữ liệu. Nội dung bao gồm các kết quả thống kê mô tả, bảng kết quả ước lượng từ mô hình hồi quy logistic với diễn giải chi tiết, và kết quả đánh giá hiệu quả của mô hình thông qua các chỉ số trên tập dữ liệu kiểm tra.
Chương 5. Kết luận và hàm ý: Chương cuối cùng sẽ tóm tắt lại các kết quả nghiên cứu chính để trả lời cho các câu hỏi đã đặt ra. Từ đó, chương sẽ đưa ra các hàm ý về mặt quản trị cho các tổ chức tín dụng, chỉ ra những hạn chế của đề tài và đề xuất các hướng nghiên cứu tiềm năng trong tương lai.
Trong hoạt động của các tổ chức tài chính, rủi ro tín dụng được xem là loại rủi ro cơ bản và quan trọng nhất. Theo định nghĩa của Ủy ban Basel về Giám sát Ngân hàng (Basel Committee on Banking Supervision - BCBS), rủi ro tín dụng được định nghĩa là khả năng tổn thất phát sinh khi một bên vay hoặc một đối tác không thực hiện được các nghĩa vụ của mình theo các điều khoản đã thỏa thuận. Rủi ro này không chỉ bao gồm khoản tổn thất về vốn gốc và lãi dự thu mà còn bao gồm các chi phí phát sinh trong quá trình thu hồi nợ.
Rủi ro tín dụng tồn tại dưới nhiều hình thức, trong đó hai hình thức chính bao gồm:
Bản chất của rủi ro tín dụng đến từ sự bất đối xứng thông tin, khi người cho vay không thể có được thông tin đầy đủ và chính xác tuyệt đối về khả năng và sự sẵn sàng trả nợ của người đi vay. Chính vì vậy, việc lượng hóa và dự báo rủi ro này thông qua các mô hình phân tích dữ liệu là một công cụ thiết yếu để giảm thiểu sự bất đối xứng này.
Rủi ro tín dụng là một khả năng tiềm ẩn, và nó chỉ trở thành một khoản tổn thất thực tế thông qua sự kiện vỡ nợ. Một sự kiện vỡ nợ được xác định khi các điều kiện vi phạm hợp đồng tín dụng xảy ra. Trong lĩnh vực ngân hàng bán lẻ và tín dụng tiêu dùng, một định nghĩa phổ biến và được chấp nhận rộng rãi theo tiêu chuẩn của Basel II là một khách hàng được coi là vỡ nợ khi họ trễ hạn thanh toán các nghĩa vụ nợ quan trọng quá 90 ngày.
Trong bối cảnh của nghiên cứu này, biến phụ thuộc
default_payment_next_month chính là một chỉ báo cho sự kiện
vỡ nợ. Việc một khách hàng bị phân loại là “1” (có vỡ nợ) phản ánh việc
họ đã không thực hiện nghĩa vụ thanh toán tối thiểu trong kỳ sao kê tiếp
theo, đây là một dấu hiệu sớm và trực tiếp của việc rủi ro tín dụng đang
trở thành hiện thực. Do đó, mô hình hóa và dự báo sự kiện này là nhiệm
vụ cốt lõi để quản trị rủi ro.
Việc quản lý rủi ro tín dụng một cách hiệu quả có tầm quan trọng sống còn đối với cả tổ chức tài chính và toàn bộ nền kinh tế.
Đối với tổ chức tài chính:
Bảo toàn vốn và lợi nhuận: Rủi ro tín dụng không được kiểm soát sẽ dẫn đến các khoản nợ xấu, làm xói mòn trực tiếp lợi nhuận của ngân hàng thông qua việc tăng chi phí trích lập dự phòng rủi ro và mất mát vốn gốc.
Tối ưu hóa quyết định kinh doanh: Một hệ thống dự báo rủi ro tốt giúp ngân hàng đưa ra các quyết định cho vay chính xác hơn, định giá khoản vay phù hợp với mức độ rủi ro, và phân bổ vốn hiệu quả vào các danh mục đầu tư an toàn.
Duy trì thanh khoản và uy tín: Tỷ lệ nợ xấu cao có thể gây ra khủng hoảng thanh khoản và làm suy giảm niềm tin của người gửi tiền, cổ đông và các đối tác trên thị trường.
Đối với nền kinh tế:
Ổn định hệ thống tài chính: Sức khỏe của từng ngân hàng riêng lẻ là nền tảng cho sự ổn định của cả hệ thống. Nếu nhiều tổ chức cùng lúc đối mặt với rủi ro tín dụng cao, nó có thể gây ra hiệu ứng lan truyền, dẫn đến rủi ro hệ thống và có thể châm ngòi cho một cuộc khủng hoảng tài chính.
Thúc đẩy tăng trưởng kinh tế: Một hệ thống tín dụng lành mạnh, vận hành dựa trên các nguyên tắc quản trị rủi ro tốt, sẽ đảm bảo dòng vốn được lưu thông hiệu quả đến các doanh nghiệp và cá nhân có tiềm năng, từ đó thúc đẩy đầu tư, tiêu dùng và tăng trưởng kinh tế bền vững.
Khi biến phụ thuộc là một biến nhị phân (ví dụ: Vỡ nợ/Không vỡ nợ),
các mô hình hồi quy tuyến tính cổ điển (OLS) trở nên không phù hợp. Thay
vào đó, một lớp các mô hình được gọi là Mô hình Lựa chọn Nhị
phân được sử dụng. Các mô hình này không dự báo trực tiếp giá
trị 0 hay 1, mà thay vào đó, chúng mô hình hóa xác suất
để biến phụ thuộc nhận giá trị là 1, P(Y=1 | X), dựa trên
các biến độc lập X.
Điểm khác biệt cốt lõi giữa các mô hình này nằm ở hàm phân phối tích lũy mà chúng sử dụng để tổ hợp tuyến tính của các biến độc lập vào một khoảng xác suất (0, 1). Ba mô hình phổ biến nhất trong lớp này là Logit, Probit, và Complementary Log-log.
Đây là mô hình phổ biến và được sử dụng chính trong nghiên cứu này. Mô hình Logit giả định rằng log-odds của xác suất tuân theo một phân phối logistic.
Tổ hợp tuyến tính:
\[z = \beta_0 + \beta_1 X_1 + \beta_2 X_2 + \ldots + \beta_k X_k\]
Hàm liên kết (Link Function): Hàm Logit, được xây dựng từ hàm phân phối tích lũy Logistic (hàm sigmoid).
\[P(Y=1 | X) = \frac{e^z}{1 + e^z} = \frac{1}{1 + e^{-z}}\]
Phương trình ước lượng:
\[\ln\left(\frac{P}{1 - P}\right) = \beta_0 + \beta_1 X_1 + \dots + \beta_k X_k\]
Đặc điểm: Mô hình Logit tương đối dễ tính toán và các hệ số của nó có thể được diễn giải một cách trực quan thông qua Tỷ lệ chênh (Odds Ratio). Đuôi của phân phối logistic “dày” hơn so với phân phối chuẩn, có nghĩa là nó ít nhạy cảm hơn với các quan sát ngoại lệ.
Mô hình Probit là một lựa chọn thay thế rất phổ biến cho Logit, đặc biệt trong kinh tế học. Nó giả định rằng xác suất lựa chọn tuân theo phân phối chuẩn tích lũy.
Tổ hợp tuyến tính:
\[z = \beta_0 + \beta_1 X_1 + \beta_2 X_2 + \ldots + \beta_k X_k\]
Hàm liên kết (Link Function): Hàm Probit, chính là hàm phân phối tích lũy của phân phối chuẩn tắc, thường được ký hiệu là \(Φ\).
\[P(Y=1 | X) = \Phi(z) = \int_{-\infty}^{z} \frac{1}{\sqrt{2\pi}} e^{-\frac{t^2}{2}} dt\]
Đặc điểm: Mô hình Probit được cho là có nền tảng lý thuyết vững chắc hơn trong một số lĩnh vực (ví dụ như lý thuyết hữu dụng ngẫu nhiên). Tuy nhiên, các hệ số của nó không thể diễn giải trực tiếp một cách dễ dàng như Odds Ratio. Thay vào đó, người ta thường phải tính toán và diễn giải “hiệu ứng biên”. Trong thực tế, với hầu hết các bộ dữ liệu, kết quả dự báo của mô hình Logit và Probit rất hiếm khi khác biệt một cách đáng kể.
Mô hình Clog-log ít phổ biến hơn nhưng lại rất hữu ích trong một số trường hợp cụ thể. Nó sử dụng một hàm liên kết bất đối xứng, dựa trên phân phối Gumbel (hay phân phối giá trị cực trị loại I).
Tổ hợp tuyến tính:
\[z = \beta_0 + \beta_1 X_1 + \beta_2 X_2 + \ldots + \beta_k X_k\]
Hàm liên kết (Link Function): Hàm Complementary Log-log.
\[P(Y=1 | X) = 1 - e^{-e^z}\]
Đặc điểm: Do tính bất đối xứng, mô hình Clog-log đặc biệt phù hợp khi xác suất của một sự kiện (Y=1) tiến đến 0 hoặc 1 với tốc độ khác nhau. Ví dụ, nó thường được sử dụng trong các bài toán mà sự kiện “thành công” (Y=1) là rất hiếm hoặc rất phổ biến. Trong khi Logit và Probit đối xứng quanh xác suất 0.5, Clog-log thì không.
Không giống như mô hình hồi quy tuyến tính sử dụng phương pháp Bình phương Tối thiểu (OLS), các hệ số \((\beta_0, \beta_1, \dots)\) của mô hình hồi quy logistic được ước lượng bằng phương pháp Ước lượng Hợp lý Cực đại (MLE).
Về bản chất, MLE là một phương pháp thống kê nhằm tìm ra một bộ giá trị tham số (các hệ số \(\beta\)) sao cho bộ tham số đó làm cho xác suất xảy ra của bộ dữ liệu quan sát được là lớn nhất. Nói một cách trực quan, phương pháp này cố gắng trả lời câu hỏi: “Nếu chúng ta có một bộ dữ liệu đã quan sát, đâu là các giá trị hệ số \(\beta\) của mô hình mà có khả năng nhất đã tạo ra kết quả thực tế này?”
Quá trình này bao gồm các bước:
Xây dựng hàm hợp lý (Likelihood Function): Một hàm số được xây dựng để biểu diễn xác suất của toàn bộ dữ liệu quan sát được, phụ thuộc vào các hệ số β chưa biết.
Tối đa hóa hàm hợp lý: Do tính toán phức tạp, hàm hợp lý thường được chuyển sang dạng logarit (log-likelihood). Sau đó, các phần mềm thống kê như R sẽ sử dụng các thuật toán tối ưu hóa lặp (ví dụ như Newton-Raphson) để tìm ra bộ hệ số β giúp tối đa hóa hàm log-likelihood này.
Kết quả ước lượng: Các giá trị hệ số β tìm được
ở bước cuối cùng chính là các ước lượng hợp lý cực đại. Đây là các giá
trị được trình bày trong bảng kết quả của hàm glm() trong
R.
Lịch sử của việc đánh giá rủi ro tín dụng đã trải qua một quá trình phát triển lâu dài. Công trình kinh điển của Altman (1968), với mô hình Z-score sử dụng phương pháp phân tích biệt số (discriminant analysis) để dự báo khả năng phá sản của doanh nghiệp, được xem là một trong những nghiên cứu nền tảng, đánh dấu sự chuyển dịch từ đánh giá định tính sang các mô hình định lượng. Kể từ đó, việc ứng dụng các mô hình thống kê vào chấm điểm tín dụng đã trở thành một lĩnh vực nghiên cứu sôi nổi. Trong số các phương pháp được đề xuất, hồi quy logistic nhanh chóng nổi lên như một công cụ phổ biến nhờ sự cân bằng giữa hiệu quả và khả năng diễn giải.
Qua nhiều thập kỷ nghiên cứu, các học giả đã xác định được nhiều nhóm yếu tố có khả năng dự báo rủi ro vỡ nợ.
Nhóm yếu tố nhân khẩu học và kinh tế - xã hội: Các đặc điểm như tuổi, giới tính, trình độ học vấn, tình trạng hôn nhân và số người phụ thuộc thường xuyên được đưa vào các mô hình như những biến kiểm soát. Tuy nhiên, nhiều nghiên cứu cho thấy sức mạnh dự báo của chúng thường không cao bằng các biến hành vi. Ví dụ, Limsombunchai và cộng sự (2004) khi nghiên cứu về các khoản vay nông nghiệp ở Thái Lan đã kết luận rằng các yếu tố nhân khẩu học có ảnh hưởng, nhưng không phải là các yếu tố quyết định mạnh nhất.
Nhóm yếu tố hành vi và lịch sử tín dụng: Đây là nhóm yếu tố được cộng đồng nghiên cứu đồng thuận là có sức mạnh dự báo vượt trội. Lý thuyết cho rằng “hành vi quá khứ là chỉ báo tốt nhất cho hành vi tương lai” được thể hiện rất rõ trong lĩnh vực tín dụng.
Trong một bài tổng quan có ảnh hưởng lớn, Hand và Henley (1997) đã khẳng định rằng các biến liên quan đến lịch sử trả nợ (ví dụ: số lần trễ hạn) là những yếu tố dự báo mạnh mẽ và ổn định nhất trong các mô hình chấm điểm tín dụng.
Cụ thể hơn, trong một nghiên cứu trên thị trường thẻ tín dụng Đài
Loan cùng bối cảnh với bộ dữ liệu của đề tài này Lee và Chen (2005) đã
chỉ ra rằng các biến số phản ánh tình trạng trả nợ trong các tháng trước
đó (PAY_0, PAY_2, …) có vai trò cực kỳ quan
trọng và là những nhân tố quyết định đến khả năng vỡ nợ.
Yeh và Chi (2009) cũng thực hiện một nghiên cứu trên dữ liệu thẻ tín dụng Đài Loan và kết luận rằng các đặc điểm về hành vi thanh toán cung cấp nhiều thông tin dự báo hơn đáng kể so với các đặc điểm nhân khẩu học.
Hồi quy logistic từ lâu đã được coi là mô hình “tiêu chuẩn vàng” (gold standard) trong ngành và trong các nghiên cứu học thuật. Lý do chính là khả năng diễn giải trực tiếp của các hệ số mô hình, giúp các nhà quản lý rủi ro hiểu được yếu tố nào đang tác động và tác động như thế nào, điều này rất quan trọng đối với việc tuân thủ các quy định pháp lý (như Quy tắc Bình đẳng Cơ hội Tín dụng ở Hoa Kỳ). Hand và Henley (1997) cũng ghi nhận hồi quy logistic là một trong những phương pháp hiệu quả và được ưa chuộng nhất.
Tuy nhiên, với sự phát triển của học máy, nhiều nghiên cứu đã so sánh hiệu quả của hồi quy logistic với các thuật toán phức tạp hơn. Lee và Chen (2005) đã so sánh hồi quy logistic với mạng nơ-ron (neural networks) và kết luận rằng trong khi các mô hình phức tạp hơn có thể nhỉnh hơn một chút về độ chính xác, hồi quy logistic vẫn là một công cụ cạnh tranh, mạnh mẽ và là một điểm chuẩn (benchmark) rất khó bị đánh bại. Tương tự, Yeh và Chi (2009) khi so sánh nhiều kỹ thuật khác nhau cũng thấy rằng sự khác biệt về hiệu suất dự báo giữa các mô hình không quá lớn, điều này càng củng cố vị thế của hồi quy logistic như một lựa chọn hợp lý, cân bằng giữa độ chính xác và tính dễ diễn giải.
Lược khảo các công trình đi trước cho thấy hai điểm chính: Các yếu tố về hành vi tín dụng là nền tảng của một mô hình dự báo rủi ro hiệu quả; và Hồi quy logistic là một phương pháp luận vững chắc, đã được kiểm chứng và được công nhận rộng rãi.
Do đó, nghiên cứu này không nhằm mục tiêu phát triển một thuật toán hoàn toàn mới, mà tập trung vào việc áp dụng và kiểm định mô hình hồi quy logistic, một phương pháp kinh điển trên một bộ dữ liệu công khai. Mục đích là để tái khẳng định và lượng hóa mức độ ảnh hưởng của các yếu tố đã được xác định trong các nghiên cứu trước (đặc biệt là các yếu tố hành vi) trong bối cảnh cụ thể của dữ liệu, qua đó cung cấp một ví dụ điển hình về quy trình phân tích rủi ro tín dụng bằng phần mềm R.
Nghiên cứu này sử dụng bộ dữ liệu thứ cấp có tên “Default of Credit Card Clients” từ Kho lưu trữ Học máy của UCI. Bộ dữ liệu ghi nhận thông tin của 30.000 khách hàng thẻ tín dụng tại Đài Loan trong năm 2005.
Để có một cái nhìn tổng quan về cấu trúc, kiểu dữ liệu của từng biến và kích thước của bộ dữ liệu, kết quả từ hàm str() được trình bày dưới đây.
## ```
## Classes 'tbl_df', 'tbl' and 'data.frame': 30000 obs. of 24 variables:
## $ LIMIT_BAL : num 20000 120000 90000 50000 50000 50000 500000 100000 140000 20000 ...
## $ SEX : num 2 2 2 2 1 1 1 2 2 1 ...
## $ EDUCATION : num 2 2 2 2 2 1 1 2 3 3 ...
## $ MARRIAGE : num 1 2 2 1 1 2 2 2 1 2 ...
## $ AGE : num 24 26 34 37 57 37 29 23 28 35 ...
## $ PAY_0 : num 2 -1 0 0 -1 0 0 0 0 -2 ...
## $ PAY_2 : num 2 2 0 0 0 0 0 -1 0 -2 ...
## $ PAY_3 : num -1 0 0 0 -1 0 0 -1 2 -2 ...
## $ PAY_4 : num -1 0 0 0 0 0 0 0 0 -2 ...
## $ PAY_5 : num -2 0 0 0 0 0 0 0 0 -1 ...
## $ PAY_6 : num -2 2 0 0 0 0 0 -1 0 -1 ...
## $ BILL_AMT1 : num 3913 2682 29239 46990 8617 ...
## $ BILL_AMT2 : num 3102 1725 14027 48233 5670 ...
## $ BILL_AMT3 : num 689 2682 13559 49291 35835 ...
## $ BILL_AMT4 : num 0 3272 14331 28314 20940 ...
## $ BILL_AMT5 : num 0 3455 14948 28959 19146 ...
## $ BILL_AMT6 : num 0 3261 15549 29547 19131 ...
## $ PAY_AMT1 : num 0 0 1518 2000 2000 ...
## $ PAY_AMT2 : num 689 1000 1500 2019 36681 ...
## $ PAY_AMT3 : num 0 1000 1000 1200 10000 657 38000 0 432 0 ...
## $ PAY_AMT4 : num 0 1000 1000 1100 9000 ...
## $ PAY_AMT5 : num 0 0 1000 1069 689 ...
## $ PAY_AMT6 : num 0 2000 5000 1000 679 ...
## $ default_payment_next_month: num 1 1 0 0 0 0 0 0 0 0 ...
## ```
Bộ dữ liệu gốc bao gồm 30.000 quan sát, tương ứng với 30.000 khách hàng cá nhân sử dụng dịch vụ thẻ tín dụng tại một ngân hàng ở Đài Loan. Dữ liệu ghi nhận các thông tin nhân khẩu học và lịch sử tín dụng của các khách hàng này trong khoảng thời gian 6 tháng, từ tháng 4 năm 2005 đến tháng 9 năm 2005.
Dưới đây là 6 dòng dữ liệu đầu tiên, giúp có cái nhìn cụ thể hơn về các giá trị trong bộ dữ liệu gốc:
##
## Attaching package: 'dplyr'
## The following objects are masked from 'package:stats':
##
## filter, lag
## The following objects are masked from 'package:base':
##
## intersect, setdiff, setequal, union
LIMIT_BAL | SEX | EDUCATION | MARRIAGE | AGE | PAY_0 | PAY_2 | PAY_3 | PAY_4 | PAY_5 | PAY_6 | BILL_AMT1 | BILL_AMT2 | BILL_AMT3 | BILL_AMT4 | BILL_AMT5 | BILL_AMT6 | PAY_AMT1 | PAY_AMT2 | PAY_AMT3 | PAY_AMT4 | PAY_AMT5 | PAY_AMT6 | default_payment_next_month |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
20,000 | 2 | 2 | 1 | 24 | 2 | 2 | -1 | -1 | -2 | -2 | 3,913 | 3,102 | 689 | 0 | 0 | 0 | 0 | 689 | 0 | 0 | 0 | 0 | 1 |
120,000 | 2 | 2 | 2 | 26 | -1 | 2 | 0 | 0 | 0 | 2 | 2,682 | 1,725 | 2,682 | 3,272 | 3,455 | 3,261 | 0 | 1,000 | 1,000 | 1,000 | 0 | 2,000 | 1 |
90,000 | 2 | 2 | 2 | 34 | 0 | 0 | 0 | 0 | 0 | 0 | 29,239 | 14,027 | 13,559 | 14,331 | 14,948 | 15,549 | 1,518 | 1,500 | 1,000 | 1,000 | 1,000 | 5,000 | 0 |
50,000 | 2 | 2 | 1 | 37 | 0 | 0 | 0 | 0 | 0 | 0 | 46,990 | 48,233 | 49,291 | 28,314 | 28,959 | 29,547 | 2,000 | 2,019 | 1,200 | 1,100 | 1,069 | 1,000 | 0 |
50,000 | 1 | 2 | 1 | 57 | -1 | 0 | -1 | 0 | 0 | 0 | 8,617 | 5,670 | 35,835 | 20,940 | 19,146 | 19,131 | 2,000 | 36,681 | 10,000 | 9,000 | 689 | 679 | 0 |
50,000 | 1 | 1 | 2 | 37 | 0 | 0 | 0 | 0 | 0 | 0 | 64,400 | 57,069 | 57,608 | 19,394 | 19,619 | 20,024 | 2,500 | 1,815 | 657 | 1,000 | 1,000 | 800 | 0 |
Bộ dữ liệu bao gồm 24 biến số, được sử dụng để mô tả đặc điểm và hành vi của khách hàng. Bảng 3.2 Mô tả chi tiết ý nghĩa và thang đo của từng biến.
STT | Tên biến | Diễn giải | Thang đo |
|---|---|---|---|
1 | LIMIT_BAL | Hạn mức tín dụng được cấp (đơn vị: Đài tệ) | Định lượng |
2 | SEX | Giới tính (1 = Nam, 2 = Nữ) | Định tính |
3 | EDUCATION | Trình độ học vấn (1 = Sau đại học, 2 = Đại học, 3 = Trung học phổ thông, 4 = Khác) | Định tính |
4 | MARRIAGE | Tình trạng hôn nhân (1 = Kết hôn, 2 = Độc thân, 3 = Khác) | Định tính |
5 | AGE | Tuổi (năm) | Định lượng |
6 | PAY_0 | Tình trạng trả nợ tháng 9/2005 (-2 = trả đúng hạn và chưa phát sinh chi tiêu, -1 = trả đúng hạn, 0 = quay vòng tín dụng, 1 = trễ 1 tháng, ..., 9 = trễ 9 tháng trở lên) | Định tính (Thứ bậc) |
7 | PAY_2 | Tình trạng trả nợ tháng 8/2005 | Định tính (Thứ bậc) |
8 | PAY_3 | Tình trạng trả nợ tháng 7/2005 | Định tính (Thứ bậc) |
9 | PAY_4 | Tình trạng trả nợ tháng 6/2005 | Định tính (Thứ bậc) |
10 | PAY_5 | Tình trạng trả nợ tháng 5/2005 | Định tính (Thứ bậc) |
11 | PAY_6 | Tình trạng trả nợ tháng 4/2005 | Định tính (Thứ bậc) |
12 | BILL_AMT1 | Số tiền sao kê tháng 9/2005 (đơn vị: Đài tệ) | Định lượng |
13 | BILL_AMT2 | Số tiền sao kê tháng 8/2005 | Định lượng |
14 | BILL_AMT3 | Số tiền sao kê tháng 7/2005 | Định lượng |
15 | BILL_AMT4 | Số tiền sao kê tháng 6/2005 | Định lượng |
16 | BILL_AMT5 | Số tiền sao kê tháng 5/2005 | Định lượng |
17 | BILL_AMT6 | Số tiền sao kê tháng 4/2005 | Định lượng |
18 | PAY_AMT1 | Khoản thanh toán trước đó vào tháng 9/2005 (đơn vị: Đài tệ) | Định lượng |
19 | PAY_AMT2 | Khoản thanh toán trước đó vào tháng 8/2005 | Định lượng |
20 | PAY_AMT3 | Khoản thanh toán trước đó vào tháng 7/2005 | Định lượng |
21 | PAY_AMT4 | Khoản thanh toán trước đó vào tháng 6/2005 | Định lượng |
22 | PAY_AMT5 | Khoản thanh toán trước đó vào tháng 5/2005 | Định lượng |
23 | PAY_AMT6 | Khoản thanh toán trước đó vào tháng 4/2005 | Định lượng |
24 | default_payment_next_month | Biến mục tiêu: Khả năng vỡ nợ tháng tới (1 = Có vỡ nợ, 0 = Không vỡ nợ) | Định tính (Nhị phân) |
Dựa trên mục tiêu nghiên cứu, các biến trong bộ dữ liệu được xác định vai trò như sau:
Biến phụ thuộc: Biến phụ thuộc của mô hình là
default_payment_next_month. Đây là một biến nhị phân, phản
ánh khả năng vỡ nợ của khách hàng trong kỳ sao kê tiếp theo (tháng 10
năm 2005). Biến này nhận hai giá trị:
Giá trị 1: Khách hàng được ghi nhận là có vỡ nợ.
Giá trị 0: Khách hàng được ghi nhận là không vỡ nợ (thanh toán đúng hạn).
Biến độc lập: Là 23 biến còn lại, được sử dụng để giải thích và dự báo cho sự thay đổi của biến phụ thuộc. Các biến này có thể được phân thành ba nhóm chính:
Nhóm biến nhân khẩu học: SEX,
EDUCATION, MARRIAGE,
AGE.
Nhóm biến tài chính:
LIMIT_BAL.
Nhóm biến lịch sử hành vi tín dụng:
PAY_0, PAY_2 đến PAY_6,
BILL_AMT1 đến BILL_AMT6, và
PAY_AMT1 đến PAY_AMT6.
Dựa trên mục tiêu nghiên cứu, cơ sở lý thuyết về hồi quy logistic và các công trình lược khảo, nghiên cứu này xây dựng một mô hình dự báo nhằm lượng hóa tác động của các yếu tố khác nhau đến khả năng vỡ nợ của khách hàng. Mô hình này được trình bày dưới dạng một phương trình hồi quy logistic tổng quát, trong đó biến phụ thuộc là xác suất vỡ nợ, và các biến độc lập là tập hợp các đặc điểm của khách hàng.
Biến phụ thuộc của mô hình là default_payment_next_month
(kí hiệu là Y), một biến nhị phân nhận giá trị 1 nếu khách hàng vỡ nợ và
0 nếu ngược lại. Mô hình sẽ ước lượng xác suất để một khách hàng i vỡ
nợ, \(P(Y_i = 1)\), dựa trên một véc-tơ
các biến độc lập \(X_i\).
Phương trình hồi quy logistic của mô hình nghiên cứu có dạng logit như sau:
\[\ln\left(\frac{P_i}{1 - P_i}\right) = \beta_0 + \beta_1 \text{LIMIT_BAL}_i + \beta_2 \text{SEX}_i + \beta_3 \text{EDUCATION}_i + \beta_4 \text{MARRIAGE}_i + \beta_5 \text{AGE}_i + \sum_{k=1}^{N_1} \beta_{j_k} \text{PAY_k}_i + \sum_{l=1}^{N_2} \beta_{m_l} \text{BILL_AMT}_{l_i} + \sum_{p=1}^{N_3} \beta_{n_p} \text{PAY_AMT}_{p_i} + \varepsilon_i\]
Trong đó:
\(P_i\) là xác suất khách hàng i vỡ nợ.
\(\ln\left(\frac{P_i}{1 - P_i}\right)\) là log-odds của việc vỡ nợ.
\({β_0}\) là hệ số chặn (intercept).
\({β_1}\) đến \({β_n}\) là các hệ số hồi quy cần ước lượng, phản ánh mức độ thay đổi trong log-odds của việc vỡ nợ khi biến độc lập tương ứng thay đổi một đơn vị, trong điều kiện các biến khác không đổi.
Các biến độc lập bao gồm:
Nhóm yếu tố Nhân khẩu học: SEX,
EDUCATION, MARRIAGE,
AGE.
Yếu tố Tài chính:
LIMIT_BAL.
Nhóm yếu tố Lịch sử Hành vi Tín dụng:
PAY_k (tình trạng trả nợ từ tháng 4-9),
BILL_AMTₗ (số tiền trên sao kê từ tháng 4-9), và
PAY_AMTₚ (số tiền đã thanh toán từ tháng 4-9).
\(\varepsilon_i\) là sai số ngẫu nhiên của mô hình.
Quy trình kiểm định mô hình được thực hiện như sau: đầu tiên, các hệ số \({β}\) sẽ được ước lượng bằng phương pháp Ước lượng Hợp lý Cực đại (MLE) trên tập dữ liệu huấn luyện. Sau đó, nghiên cứu sẽ kiểm tra ý nghĩa thống kê của từng hệ số thông qua giá trị p-value. Một hệ số có p-value nhỏ hơn mức ý nghĩa 0.05 được xem là có ảnh hưởng thực sự đến khả năng vỡ nợ. Dấu của hệ số (dương hoặc âm) và giá trị Odds Ratio (\(exp(β)\)) sẽ được sử dụng để diễn giải chiều hướng và mức độ của tác động đó. Cuối cùng, khả năng dự báo tổng thể của mô hình sẽ được đánh giá trên tập dữ liệu kiểm tra.
Bộ dữ liệu gốc có định dạng file Excel. Gói readxl được
sử dụng để thực hiện việc này. Trong file gốc là có một dòng tiêu đề
thừa ở hàng đầu tiên, do đó, tùy chọn skip = 1 được sử dụng
để bỏ qua dòng này và đọc dòng thứ hai làm tên cột.
Sau khi nhập dữ liệu thành công, cấu trúc của bộ dữ liệu được kiểm
tra sơ bộ bằng các hàm str() và head() để đảm
bảo dữ liệu được đọc đúng định dạng và số lượng.
Dựa trên tài liệu mô tả của bộ dữ liệu và quá trình khám phá ban đầu,
một số biến định tính (EDUCATION, MARRIAGE) có
chứa các giá trị không được định nghĩa rõ ràng (ví dụ: 0,
5, 6 trong biến EDUCATION và
0 trong biến MARRIAGE). Mặc dù số lượng các
giá trị này không lớn, để đảm bảo tính nhất quán và dễ diễn giải, chúng
được gộp lại thành một hạng mục duy nhất là “Khác” (mã hóa là
4). Thực hiện bằng cách thay thế các giá trị
0, 5, 6 bằng giá trị
4 trong biến EDUCATION và 0 bằng
3 trong biến MARRIAGE.
Ngoài ra, quá trình kiểm tra bằng hàm sum(is.na()) xác
nhận rằng bộ dữ liệu này sạch và không chứa giá trị bị thiếu (NA)
nào.
Các biến định tính: Các biến có bản chất là phân
loại, bao gồm SEX, EDUCATION,
MARRIAGE và biến phụ thuộc
default_payment_next_month, được chuyển đổi từ kiểu số
(numeric) sang kiểu factor. Việc chuyển đổi này giúp R hiểu
rằng đây là các biến phân loại chứ không phải các con số có thể thực
hiện phép tính toán học.
Các biến định lượng: Các biến còn lại như
LIMIT_BAL, AGE, các biến BILL_AMT
và PAY_AMT được giữ nguyên ở định dạng số.
Một số tên cột trong bộ dữ liệu gốc có chứa khoảng trắng hoặc các ký
tự đặc biệt (ví dụ: default payment next month), gây khó
khăn và bất tiện khi viết mã lệnh. Các tên biến này đã được điều chỉnh
lại theo một quy tắc chung (ví dụ:
default_payment_next_month) bằng cách sử dụng hàm
rename() từ gói dplyr. Sau khi hoàn thành các
bước trên, bộ dữ liệu đã ở trạng thái sạch, có cấu trúc rõ ràng và sẵn
sàng cho các bước phân tích khám phá và mô hình hóa ở chương tiếp
theo.
Thống kê mô tả:
Đối với các biến định tính (như
SEX, EDUCATION, MARRIAGE, và biến
phụ thuộc default_payment_next_month), nghiên cứu sử dụng
bảng tần suất và tỷ lệ phần trăm để mô tả sự phân bổ của các quan sát
trong từng hạng mục. Trực quan hóa được thực hiện bằng biểu đồ.
Đối với các biến định lượng (như
LIMIT_BAL, AGE), nghiên cứu sử dụng các đại
lượng thống kê mô tả bao gồm: các số đo xu hướng trung tâm (giá trị
trung bình, trung vị) và các số đo độ phân tán (độ lệch chuẩn, giá trị
nhỏ nhất, giá trị lớn nhất). Trực quan hóa được thực hiện bằng biểu
đồ.
Ước lượng và Kiểm định thống kê:
Ước lượng khoảng tin cậy cho tỷ lệ: Nghiên cứu
sẽ tiến hành ước lượng khoảng tin cậy 95% cho tỷ lệ khách hàng vỡ nợ
tổng thể (default_payment_next_month = 1). Phương pháp này
cho phép từ tỷ lệ trong mẫu suy rộng ra một khoảng giá trị mà tỷ lệ thực
trong tổng thể có khả năng nằm trong đó với một độ tin cậy cho
trước.
Kiểm định giả thuyết về tỷ lệ: Để đưa ra các kết luận mang tính thống kê, kiểm định giả thuyết về một tỷ lệ được sử dụng. Ví dụ, để kiểm định xem tỷ lệ vỡ nợ trong mẫu có thực sự khác biệt so với một ngưỡng kỳ vọng nào đó hay không.
Phân tích mối quan hệ hai biến:
Giữa hai biến định tính: Nghiên cứu sử dụng bảng
chéo để kiểm tra tần suất kết hợp giữa các hạng mục. Kiểm định Chi-bình
phương được áp dụng để xác định xem có tồn tại mối liên hệ ý nghĩa thống
kê giữa hai biến hay không (ví dụ: giữa EDUCATION và
default_payment_next_month). Giả thuyết không \((H_0)\) của kiểm định này là hai biến độc
lập với nhau.
Giữa một biến định lượng và một biến định tính:
Để so sánh sự khác biệt của một biến định lượng (ví dụ:
LIMIT_BAL) giữa các nhóm của biến định tính (ví dụ: nhóm vỡ
nợ và không vỡ nợ), nghiên cứu sử dụng biểu đồ hộp để trực quan hóa và
so sánh các đặc điểm phân phối như trung vị, phân vị.
Lựa chọn mô hình:
Dựa trên cơ sở lý thuyết đã trình bày ở Chương 2 và bản chất nhị phân
của biến phụ thuộc (default_payment_next_month), mô hình
Hồi quy Logistic được lựa chọn làm công cụ phân tích chính. Mô hình này
không chỉ cho phép dự báo khả năng xảy ra của một sự kiện mà còn giúp
lượng hóa mức độ ảnh hưởng của từng biến độc lập lên khả năng đó, trong
khi đã kiểm soát ảnh hưởng của các biến khác trong mô hình.
Phân chia dữ liệu:
Để đánh giá hiệu quả của mô hình một cách khách quan và tránh hiện
tượng overfitting, bộ dữ liệu gốc (30.000 quan sát) được phân chia ngẫu
nhiên thành hai tập riêng biệt bằng cách sử dụng gói
caTools trong R:
Tập huấn luyện (Training Set): Chiếm 70% số quan sát. Tập dữ liệu này được sử dụng để xây dựng mô hình hồi quy logistic, tức là để tìm ra các hệ số hồi quy tối ưu.
Tập kiểm tra (Testing Set): Chiếm 30% số quan sát còn lại. Tập dữ liệu này được giữ riêng và chỉ được sử dụng một lần duy nhất ở bước cuối cùng để đánh giá hiệu suất của mô hình trên “dữ liệu mới” mà nó chưa từng thấy trước đó.
Hàm set.seed() được sử dụng trước khi phân chia để đảm
bảo kết quả phân chia ngẫu nhiên có thể được tái lập một cách chính xác
trong các lần chạy sau.
Sau khi mô hình hồi quy logistic được xây dựng trên tập huấn luyện, hiệu suất của nó sẽ được đánh giá một cách khách quan trên tập kiểm tra. Việc đánh giá này dựa trên một tập hợp các tiêu chí định lượng, được tính toán từ việc so sánh kết quả dự báo của mô hình với kết quả thực tế.
Ma trận nhầm lẫn là một bảng tóm tắt kết quả phân loại, làm nền tảng cho hầu hết các chỉ số đánh giá khác. Ma trận này có dạng bảng 2x2, đối chiếu giữa giá trị dự báo và giá trị thực tế, bao gồm 4 thành phần cốt lõi:
True Positive (TP): Các trường hợp mô hình dự báo đúng là “Vỡ nợ” và thực tế khách hàng đó đã vỡ nợ.
True Negative (TN): Các trường hợp mô hình dự báo đúng là “Không vỡ nợ” và thực tế khách hàng đó không vỡ nợ.
False Positive (FP - Lỗi loại I): Các trường hợp mô hình dự báo sai là “Vỡ nợ” trong khi thực tế khách hàng không vỡ nợ. Đây là trường hợp một khách hàng tốt bị nhận diện nhầm là khách hàng rủi ro.
False Negative (FN - Lỗi loại II): Các trường hợp mô hình dự báo sai là “Không vỡ nợ” trong khi thực tế khách hàng đã vỡ nợ. Đây là trường hợp bỏ sót, không nhận diện được một khách hàng rủi ro. Trong bài toán tín dụng, lỗi loại II thường được coi là nghiêm trọng hơn vì nó dẫn đến tổn thất tài chính trực tiếp.
Từ các giá trị trong ma trận nhầm lẫn, các chỉ số hiệu suất sau được tính toán:
\[\text{Accuracy} = \frac{\text{TP} + \text{TN}}{\text{TP} + \text{TN} + \text{FP} + \text{FN}}\]
\[\text{Precision} = \frac{\text{TP}}{\text{TP} + \text{FP}}\]
\[\text{Recall} = \frac{\text{TP}}{\text{TP} + \text{FN}}\]
\[\text{F1-Score} = 2 \times \frac{\text{Precision} \times \text{Recall}}{\text{Precision} + \text{Recall}}\]
\[\text{False Positive Rate} = \frac{\text{FP}}{\text{FP} + \text{TN}}\]
Một mô hình càng tốt, đường cong ROC của nó càng tiến gần về góc trên bên trái của biểu đồ.
Chỉ số AUC (Area Under the Curve - Diện tích dưới đường cong): Là giá trị diện tích nằm bên dưới đường cong ROC, nhận giá trị từ 0.5 đến 1.0. AUC cung cấp một thước đo tổng hợp duy nhất về hiệu suất của mô hình, không phụ thuộc vào một ngưỡng xác suất cụ thể nào.
Chỉ số AUC đặc biệt hữu ích vì nó đánh giá khả năng của mô hình trong việc xếp hạng các quan sát một cách chính xác tức là khả năng mô hình gán một xác suất vỡ nợ cao hơn cho một khách hàng ngẫu nhiên thực sự vỡ nợ so với một khách hàng ngẫu nhiên không vỡ nợ.
Phân tích bắt đầu với biến phụ thuộc default_payment_next_month trên tập huấn luyện (train_set) để hiểu rõ đặc điểm của dữ liệu sẽ được dùng để xây dựng mô hình. Bảng 4.1 và Hình 4.1 dưới đây trình bày tần suất và tỷ lệ của hai nhóm khách hàng.
Tình trạng | Số lượng | Tỷ lệ (%) |
|---|---|---|
Không vỡ nợ (0) | 16,355 | 77.88 |
Vỡ nợ (1) | 4,645 | 22.12 |
Trên tập huấn luyện, có 4,645 khách hàng được ghi nhận vỡ nợ, chiếm 22.12%. Điều này cho thấy sự mất cân bằng đáng kể giữa hai lớp dữ liệu Không vỡ nợ và Vỡ nợ, một đặc điểm quan trọng cần lưu ý khi xây dựng mô hình dự đoán.
Để đánh giá ý nghĩa thống kê, kiểm định giả thuyết về tỷ lệ được thực hiện:
Giả thuyết không \((H_0)\): Tỷ lệ vỡ nợ trong tổng thể là 20%.
Giả thuyết đối \((H_1)\): Tỷ lệ vỡ nợ trong tổng thể khác 20%.
Kết quả kiểm định và ước lượng:
Tỷ lệ mẫu (Vỡ nợ) | Giá trị Chi-bình phương | P-value | Bậc tự do | Giới hạn dưới KTC 95% | Giới hạn trên KTC 95% |
|---|---|---|---|---|---|
0.2212 | 58.8036 | <0.001 | 1 | 0.2156 | 0.2269 |
Kết quả phân tích cho giá trị p-value < 0.001, bác bỏ giả thuyết không \((H_0)\) và điều này khẳng định rằng tỷ lệ vỡ nợ quan sát được trong tập huấn luyện (khoảng 22.12%) có sự khác biệt ý nghĩa thống kê so với mức tham chiếu 20%.
Kết quả ước lượng khoảng tin cậy 95% cho thấy tỷ lệ vỡ nợ thực sự của tổng thể mà mẫu huấn luyện đại diện nằm trong khoảng từ 21.56% đến 22.69%. Con số này thiết lập một điểm chuẩn rủi ro cho quá trình xây dựng mô hình.
Các biến nhân khẩu học:
Để phác họa chân dung tổng thể của tệp khách hàng trong tập huấn luyện, các đặc điểm nhân khẩu học chính được phân tích. Bảng 4.3 tổng hợp sự phân bổ của khách hàng theo Giới tính, Trình độ học vấn và Tình trạng hôn nhân.
Biến | Phân loại | Số lượng | Tỷ lệ (%) |
|---|---|---|---|
Giới tính | Nam | 8,350 | 39.8 |
Nữ | 12,650 | 60.2 | |
Học vấn | Sau ĐH | 7,409 | 35.3 |
Đại học | 9,792 | 46.6 | |
THPT | 3,469 | 16.5 | |
Khác | 330 | 1.6 | |
Hôn nhân | Đã kết hôn | 9,637 | 45.9 |
Độc thân | 11,093 | 52.8 | |
Khác | 270 | 1.3 |
Để trực quan hóa sự phân bổ này, Hình 4.2 dưới đây hiển thị số lượng khách hàng tương ứng với từng nhóm.
Hình 4.2: Trực quan hóa các đặc điểm nhân khẩu học trên tập huấn luyện.
Nhận xét:
Từ Bảng 4.3 và Hình 4.2, chân dung của tệp khách hàng dùng để xây dựng mô hình được phác họa rõ nét.
Về giới tính, có sự chênh lệch đáng kể với nhóm nữ chiếm đa số (60.2%).
Về học vấn, đây là một tệp khách hàng có trình độ tương đối cao, với nhóm Đại học và Sau Đại học chiếm tổng cộng hơn 80%, gợi ý rằng sản phẩm thẻ tín dụng có thể đang nhắm đến phân khúc khách hàng có thu nhập ổn định.
Về tình trạng hôn nhân, có sự cân bằng tương đối giữa nhóm độc thân (52.8%) và nhóm đã kết hôn (45.9%).
Các biến định lượng:
Đối với các biến định lượng, phân tích mô tả sẽ tập trung vào hai
biến mang tính đặc điểm cốt lõi của khách hàng là Hạn mức tín dụng
(LIMIT_BAL) và Tuổi (AGE).
Thống kê | Hạn mức tín dụng (LIMIT_BAL) | Tuổi (AGE) |
|---|---|---|
Trung bình | 168,485 | 36 |
Độ lệch chuẩn | 129,879 | 9 |
Trung vị | 140,000 | 34 |
Giá trị nhỏ nhất | 10,000 | 21 |
Giá trị lớn nhất | 800,000 | 79 |
Nhận xét: Bảng 4.4 cho thấy hai đặc điểm quan trọng.
Thứ nhất, hạn mức tín dụng (LIMIT_BAL) có độ phân tán cực kỳ lớn, với độ lệch chuẩn (129,879) gần bằng giá trị trung bình (168,485). Sự phân hóa mạnh mẽ này gợi ý rằng đây có thể là một yếu tố phân loại rủi ro rất hiệu quả.
Thứ hai, độ tuổi trung bình của khách hàng là 36, cho thấy nhóm khách hàng chính là những người đang trong độ tuổi lao động chính.
Mối quan hệ giữa các biến Nhân khẩu học và Khả năng vỡ nợ
Để kiểm tra mối liên hệ giữa các đặc điểm nhân khẩu học và tình trạng vỡ nợ, kiểm định Chi-bình phương về tính độc lập được sử dụng. Giả thuyết chung cho các phân tích dưới đây là:
\(H_0\): Biến nhân khẩu học và tình trạng vỡ nợ là hai biến độc lập.
\(H_1\): Tồn tại mối liên hệ phụ thuộc giữa hai biến.
Trình độ học vấn (EDUCATION):
Giả thuyết \(H_0\): Trình độ học vấn và tình trạng vỡ nợ là hai biến độc lập.
Kết quả: Bảng 4.5, 4.6 và 4.7 trình bày kết quả phân tích chi tiết.
Nhom | Không vỡ nợ | Vỡ nợ | TongSo | TyLeVoNo |
|---|---|---|---|---|
Sau ĐH | 5,987 | 1,422 | 7,409 | 19.2 |
Đại học | 7,477 | 2,315 | 9,792 | 23.6 |
THPT | 2,582 | 887 | 3,469 | 25.6 |
Khác | 309 | 21 | 330 | 6.4 |
Thuoc_do | Gia_tri |
|---|---|
Rủi ro Tương đối (RR) | 1.33 |
Tỷ lệ chênh (OR) | 1.45 |
Giá trị (χ²) | P-value | df | Phương pháp |
|---|---|---|---|
121.532 | <0.001 | 3 | Pearson's Chi-squared test |
Nhận xét:
Kết quả phân tích cho thấy một mối liên hệ rõ ràng và có ý nghĩa thống kê cao giữa trình độ học vấn và khả năng vỡ nợ (p-value < 0.001). Bảng 4.5 chỉ ra một xu hướng nhất quán: tỷ lệ vỡ nợ giảm dần khi trình độ học vấn tăng, từ 25.6% ở nhóm THPT xuống chỉ còn 19.2% ở nhóm Sau Đại học.
Bảng 4.6 lượng hóa sự khác biệt này một cách cụ thể: nguy cơ vỡ nợ của một khách hàng có trình độ THPT cao hơn 1.33 lần so với một khách hàng có trình độ Sau Đại học. Phát hiện này ủng hộ mạnh mẽ giả thuyết rằng trình độ học vấn cao hơn, có thể đi kèm với sự ổn định về thu nhập và nhận thức tài chính tốt hơn, là một yếu tố giúp giảm thiểu rủi ro tín dụng.
Giới tính (SEX):
Giả thuyết \(H_0\): Giới tính và tình trạng vỡ nợ là hai biến độc lập.
Kết quả:
Nhom | Không vỡ nợ | Vỡ nợ | TongSo | TyLeVoNo |
|---|---|---|---|---|
Nam | 6,356 | 1,994 | 8,350 | 23.9 |
Nữ | 9,999 | 2,651 | 12,650 | 21.0 |
Thuoc_do | Gia_tri |
|---|---|
Rủi ro Tương đối (RR) | 1.14 |
Tỷ lệ chênh (OR) | 1.18 |
Giá trị (χ²) | P-value | df | Phương pháp |
|---|---|---|---|
24.790 | <0.001 | 1 | Pearson's Chi-squared test with Yates' continuity correction |
Nhận xét:
Phân tích mối quan hệ giữa giới tính và khả năng vỡ nợ cho thấy một
sự khác biệt có ý nghĩa thống kê (p-value = <0.001). Cụ
thể, Bảng 4.8 cho thấy tỷ lệ vỡ nợ ở nhóm nam là 23.9%, cao hơn so với
nhóm nữ là 21%.
Mặc dù sự khác biệt về tỷ lệ là không quá lớn, Bảng 4.9 cho thấy nguy cơ vỡ nợ của khách hàng nam vẫn cao hơn khoảng 14% so với khách hàng nữ (RR = 1.14). Điều này cho thấy giới tính, dù có thể không phải là yếu tố quyết định mạnh nhất, vẫn là một biến số có liên quan và cần được xem xét trong mô hình phân tích tổng thể.
Tình trạng hôn nhân (MARRIAGE):
Giả thuyết \(H_0\): Tình trạng hôn nhân và vỡ nợ là hai biến độc lập.
Kết quả:
Nhom | Không vỡ nợ | Vỡ nợ | TongSo | TyLeVoNo |
|---|---|---|---|---|
Đã kết hôn | 7,351 | 2,286 | 9,637 | 23.7 |
Độc thân | 8,798 | 2,295 | 11,093 | 20.7 |
Khác | 206 | 64 | 270 | 23.7 |
Thuoc_do | Gia_tri |
|---|---|
Rủi ro Tương đối (RR) | 1.15 |
Tỷ lệ chênh (OR) | 1.19 |
Giá trị (χ²) | P-value | df | Phương pháp |
|---|---|---|---|
27.925 | <0.001 | 2 | Pearson's Chi-squared test |
Nhận xét:
Tình trạng hôn nhân cũng cho thấy một mối liên hệ có ý nghĩa thống kê cao với khả năng vỡ nợ (p-value < 0.001). Một phát hiện đáng chú ý từ Bảng 4.11 là nhóm khách hàng đã kết hôn có tỷ lệ vỡ nợ là 23.7%, cao hơn so với nhóm độc thân là 20.7%.
Phân tích so sánh rủi ro (Bảng 4.12) củng cố thêm điều này, cho thấy nguy cơ vỡ nợ của nhóm đã kết hôn cao hơn 15% so với nhóm độc thân (RR = 1.15). Kết quả này đi ngược lại với giả định thông thường rằng hôn nhân đồng nghĩa với sự ổn định. Thay vào đó, nó ủng hộ giả thuyết rằng các gánh nặng và trách nhiệm tài chính gia tăng trong hôn nhân (như chi phí cho con cái, nhà cửa) có thể là một yếu tố làm tăng rủi ro tín dụng cho khách hàng.
Mối quan hệ giữa các biến Tài chính/Hành vi và Khả năng vỡ nợ
Nhóm biến này bao gồm rất nhiều chỉ số ghi nhận hành vi của khách
hàng theo thời gian (PAY_0…PAY_6, BILL_AMT1…BILL_AMT6,
PAY_AMT1…PAY_AMT6). Thay vì phân tích riêng lẻ từng biến trong số 18
biến này, giai đoạn này sẽ tập trung vào hai biến mang tính đại diện và
có khả năng giải thích cao nhất LIMIT_BAL
(đại diện cho tiềm lực tài chính) và PAY_0
(đại diện cho hành vi trả nợ tức thời).
LIMIT_BAL):Giả thuyết đặt ra là nhóm khách hàng vỡ nợ sẽ có hạn mức tín dụng được cấp thấp hơn so với nhóm không vỡ nợ, phản ánh sự đánh giá rủi ro ban đầu của ngân hàng.
Hình 4.3: Phân phối hạn mức tín dụng theo tình trạng vỡ nợ trên tập huấn luyện.
Nhận xét:
Hình 4.3 cho thấy một sự khác biệt rất rõ nét và có ý nghĩa về mặt kinh doanh. Nhóm khách hàng không vỡ nợ (nhóm 0) có giá trị trung vị của hạn mức tín dụng là 150,000, cao hơn 67% so với giá trị trung vị của nhóm vỡ nợ là 90,000. Toàn bộ phân phối của hạn mức ở nhóm không vỡ nợ cũng dịch chuyển lên cao hơn một cách rõ rệt. Điều này cung cấp bằng chứng trực quan mạnh mẽ rằng hạn mức tín dụng thấp là một dấu hiệu rủi ro quan trọng. Nó không chỉ phản ánh khả năng tài chính của khách hàng mà còn cho thấy sự thẩm định và đánh giá rủi ro ban đầu của chính ngân hàng đã có hiệu quả nhất định.
PAY_0):Đây được xem là biến hành vi quan trọng nhất. Giả thuyết được kiểm định là:
\(H_0\): Tình trạng thanh toán gần nhất và tình trạng vỡ nợ là hai biến độc lập.
\(H_1\): Tồn tại mối liên hệ phụ thuộc giữa tình trạng thanh toán gần nhất và tình trạng vỡ nợ.
Bảng 4.14 trình bày sự phân bổ và tỷ lệ vỡ nợ theo từng trạng thái thanh toán của tháng gần nhất.
Trạng thái | Không vỡ nợ | Vỡ nợ | TongSo | Tỷ lệ vỡ nợ (%) |
|---|---|---|---|---|
-2 | 1,675 | 253 | 1,928 | 13.1 |
-1 | 3,318 | 675 | 3,993 | 16.9 |
0 | 9,025 | 1,311 | 10,336 | 12.7 |
1 | 1,675 | 880 | 2,555 | 34.4 |
2 | 577 | 1,283 | 1,860 | 69.0 |
3+ | 85 | 243 | 328 | 74.1 |
Bảng 4.15 lượng hóa sự chênh lệch rủi ro giữa nhóm “Trễ hạn 1 tháng” và nhóm “Thanh toán đủ mức tối thiểu”.
Thuoc_do | Gia_tri |
|---|---|
Rủi ro Tương đối (RR) | 2.72 |
Tỷ lệ chênh (OR) | 3.62 |
Nhận xét:
Phân tích cho thấy một mối liên hệ cực kỳ mạnh mẽ và rõ ràng (p-value < 0.001) giữa tình trạng thanh toán gần nhất và khả năng vỡ nợ. Bảng 4.14 chỉ ra rằng tỷ lệ vỡ nợ tăng vọt từ chỉ 12.7% ở nhóm thanh toán đúng hạn (mức ‘0’) lên đến 34.4% ở nhóm chỉ vừa trễ hạn 1 tháng (mức ‘1’), và tiếp tục tăng lên 69% ở nhóm trễ hạn 2 tháng.
Bảng 4.15 lượng hóa sự nhảy vọt này: nguy cơ vỡ nợ của khách hàng trễ hạn 1 tháng cao hơn gấp 2.72 lần so với khách hàng thanh toán đúng hạn. Đây là tín hiệu rủi ro trực tiếp và quan trọng nhất trong tất cả các biến, khẳng định tầm quan trọng của hành vi thanh toán gần đây trong việc dự báo khả năng vỡ nợ.
Trước khi xây dựng mô hình hồi quy, một bước kiểm tra chẩn đoán quan trọng là xác định hiện tượng đa cộng tuyến giữa các biến độc lập. Đa cộng tuyến có thể làm cho các ước lượng hệ số của mô hình trở nên không ổn định và khó diễn giải. Phân tích này tập trung vào việc kiểm tra đa cộng tuyến giữa các biến độc lập định lượng trên train.
Để kiểm tra, Hệ số Phóng đại Phương sai (Variance Inflation Factor - VIF) được tính toán. Theo quy ước, một biến có chỉ số VIF lớn hơn 5 được xem là có vấn đề.
Bảng 4.16 trình bày kết quả kiểm tra VIF ban đầu cho các biến định lượng.
Biến số | VIF |
|---|---|
BILL_AMT2 | 25.760 |
BILL_AMT5 | 24.886 |
BILL_AMT3 | 21.725 |
BILL_AMT4 | 20.246 |
BILL_AMT6 | 14.927 |
BILL_AMT1 | 13.914 |
PAY_AMT2 | 2.223 |
PAY_AMT3 | 1.735 |
PAY_AMT1 | 1.691 |
PAY_AMT5 | 1.679 |
PAY_AMT4 | 1.629 |
LIMIT_BAL | 1.209 |
PAY_AMT6 | 1.169 |
Nhận xét
Kết quả kiểm tra (Bảng 4.16) cho thấy một vấn đề đa cộng tuyến nghiêm trọng trong nhóm biến sao kê hóa đơn. Cụ thể, sáu biến từ BILL_AMT1 đến BILL_AMT6 đều có chỉ số VIF vượt xa ngưỡng 5, với giá trị cao nhất lên tới 25.8. Điều này là hợp lý về mặt logic, vì số dư hóa đơn của các tháng liên tiếp có xu hướng tương quan rất mạnh với nhau.
Để giải quyết vấn đề này và đảm bảo độ tin cậy của mô hình, một biến đại diện mới là AVG_BILL_AMT (Số dư hóa đơn trung bình) đã được tạo ra, và sáu biến BILL_AMT gốc đã được loại bỏ. Toàn bộ quá trình này đã được thực hiện trong khâu chuẩn bị dữ liệu để tạo ra các bộ dữ liệu train_set và test_set cuối cùng.
Xác nhận kết quả:
Sau khi xử lý, chỉ số VIF được tính toán lại trên bộ dữ liệu mới
(train_set). Kết quả được trình bày trong Bảng 4.17.
Biến số | VIF |
|---|---|
PAY_AMT1 | 1.226 |
PAY_AMT3 | 1.211 |
LIMIT_BAL | 1.193 |
PAY_AMT2 | 1.190 |
AVG_BILL_AMT | 1.177 |
PAY_AMT4 | 1.140 |
PAY_AMT6 | 1.115 |
PAY_AMT5 | 1.103 |
Nhận xét:
Bảng 4.17 cho thấy, sau khi thay thế sáu biến BILL_AMT,
tất cả các biến định lượng còn lại đều có chỉ số VIF rất thấp
(dưới ngưỡng 5). Điều này xác nhận rằng vấn đề đa cộng tuyến đã
được xử lý thành công. Bộ dữ liệu đã qua xử lý (train_set và test_set)
sẽ được sử dụng để xây dựng các mô hình hồi quy ở phần tiếp theo, đảm
bảo các ước lượng hệ số sẽ ổn định và đáng tin cậy.
Sau khi vấn đề đa cộng tuyến đã được giải quyết, bước tiếp theo là
xây dựng các mô hình lựa chọn nhị phân trên tập huấn luyện đã được xử lý
(train_set). Dựa trên cơ sở lý thuyết, ba mô hình phổ biến
được xây dựng để so sánh hiệu quả: Logit, Probit, và
Cloglog.
Để lựa chọn mô hình phù hợp nhất cho việc diễn giải và dự báo, ta so sánh chúng dựa trên Tiêu chuẩn Thông tin Akaike (Akaike Information Criterion - AIC). AIC là một thước đo đánh giá sự phù hợp tương đối của mô hình, có tính đến cả độ chính xác và độ phức tạp. Theo nguyên tắc, mô hình có chỉ số AIC thấp hơn được coi là phù hợp hơn.
Bảng 4.18 trình bày kết quả so sánh chỉ số AIC của ba mô hình.
Mô hình | AIC |
|---|---|
Logit (Hồi quy Logistic) | 18,296.22 |
Probit (Hồi quy Probit) | 18,296.50 |
Cloglog (Complementary Log-log) | 18,365.25 |
Lựa chọn mô hình:
Kết quả so sánh (Bảng 4.18) cho thấy cả ba mô hình đều có chỉ số AIC rất gần nhau, chứng tỏ hiệu suất thống kê của chúng là tương đương. Mô hình Logit có chỉ số AIC thấp nhất (18,296), tuy nhiên sự khác biệt so với mô hình Probit và Cloglog là không đáng kể về mặt thực tiễn.
Do đó, dựa trên hai yếu tố: (1) có chỉ số AIC tốt nhất trên lý thuyết và (2) ưu điểm vượt trội và không thể thay thế về khả năng diễn giải kết quả một cách trực quan thông qua Tỷ lệ chênh (Odds Ratio), mô hình Logit được lựa chọn làm mô hình cuối cùng để phân tích chi tiết ở phần tiếp theo.
Bảng 4.19 trình bày kết quả ước lượng chi tiết của mô hình Logit, được xây dựng trên dữ liệu sau khi đã loại bỏ các biến đa cộng tuyến.
Bảng 4.19 trình bày kết quả của mô hình Logit sau khi đã được cải thiện bằng cách gộp các hạng mục hiếm.
Biến số | Hệ số (β) | Sai số chuẩn | P-value | Odds Ratio |
|---|---|---|---|---|
(Intercept) | -1.1306 | 0.1338 | <0.001 | 0.323 |
LIMIT_BAL | -0.0000 | 0.0000 | <0.001 | 1.000 |
SEX2 | -0.1295 | 0.0386 | <0.001 | 0.879 |
EDUCATION2 | 0.0198 | 0.0447 | 0.658 | 1.020 |
EDUCATION3 | 0.0091 | 0.0596 | 0.878 | 1.009 |
EDUCATION4 | -1.1786 | 0.2405 | <0.001 | 0.308 |
MARRIAGE2 | -0.1890 | 0.0435 | <0.001 | 0.828 |
MARRIAGE3 | -0.1009 | 0.1636 | 0.537 | 0.904 |
AGE | 0.0029 | 0.0024 | 0.217 | 1.003 |
PAY_0-1 | 0.4302 | 0.1288 | <0.001 | 1.538 |
PAY_00 | -0.3117 | 0.1392 | 0.025 | 0.732 |
PAY_01 | 0.7774 | 0.1011 | <0.001 | 2.176 |
PAY_02 | 1.9734 | 0.1264 | <0.001 | 7.195 |
PAY_03+ | 1.9546 | 0.1787 | <0.001 | 7.061 |
PAY_2-1 | -0.2666 | 0.1342 | 0.047 | 0.766 |
PAY_20 | -0.0313 | 0.1638 | 0.848 | 0.969 |
PAY_21 | -0.3862 | 0.6070 | 0.525 | 0.680 |
PAY_22 | -0.0179 | 0.1382 | 0.897 | 0.982 |
PAY_23+ | -0.0815 | 0.1951 | 0.676 | 0.922 |
PAY_3-1 | 0.0904 | 0.1274 | 0.478 | 1.095 |
PAY_30 | 0.1477 | 0.1484 | 0.319 | 1.159 |
PAY_32 | 0.4938 | 0.1500 | <0.001 | 1.639 |
PAY_33+ | 0.2338 | 0.2262 | 0.301 | 1.263 |
PAY_4-1 | -0.0991 | 0.1295 | 0.444 | 0.906 |
PAY_40 | -0.0572 | 0.1446 | 0.692 | 0.944 |
PAY_42 | 0.2065 | 0.1549 | 0.183 | 1.229 |
PAY_43+ | -0.1479 | 0.2535 | 0.560 | 0.862 |
PAY_5-1 | -0.0174 | 0.1266 | 0.891 | 0.983 |
PAY_50 | 0.1271 | 0.1404 | 0.365 | 1.136 |
PAY_52 | 0.4581 | 0.1576 | 0.004 | 1.581 |
PAY_53+ | 0.1952 | 0.2616 | 0.455 | 1.216 |
PAY_6-1 | -0.1120 | 0.0969 | 0.248 | 0.894 |
PAY_60 | -0.4354 | 0.1042 | <0.001 | 0.647 |
PAY_62 | -0.1693 | 0.1217 | 0.164 | 0.844 |
PAY_63+ | 0.2129 | 0.2327 | 0.360 | 1.237 |
PAY_AMT1 | -0.0000 | 0.0000 | <0.001 | 1.000 |
PAY_AMT2 | -0.0000 | 0.0000 | <0.001 | 1.000 |
PAY_AMT3 | -0.0000 | 0.0000 | 0.141 | 1.000 |
PAY_AMT4 | -0.0000 | 0.0000 | 0.195 | 1.000 |
PAY_AMT5 | -0.0000 | 0.0000 | 0.108 | 1.000 |
PAY_AMT6 | -0.0000 | 0.0000 | 0.232 | 1.000 |
AVG_BILL_AMT | 0.0000 | 0.0000 | <0.001 | 1.000 |
Diễn giải các hệ số hồi quy:
Từ Bảng 4.19, chúng ta có thể rút ra những nhận định quan trọng về ảnh hưởng của các yếu tố đến khả năng vỡ nợ. Việc gộp các hạng mục hiếm đã giúp ổn định đáng kể các ước lượng hệ số, đặc biệt là đối với các biến PAY_, cho phép chúng ta diễn giải kết quả một cách đáng tin cậy hơn.
Tình trạng thanh toán gần nhất (PAY_0, PAY_2, PAY_3,…):
Các hệ số cho biến PAY_0 cho thấy một xu hướng rõ ràng và có ý nghĩa thống kê cao: mức độ rủi ro tăng lên đáng kể khi tình trạng trễ hạn trở nên nghiêm trọng hơn, với nhóm tham chiếu là -2 (không có giao dịch).
Odds Ratio cho PAY_01 (Trễ 1 tháng) = 2.1758932. So với nhóm tham chiếu (-2: Không có giao dịch), khả năng vỡ nợ ở nhóm khách hàng ‘Trễ hạn 1 tháng’ cao hơn gấp 2.2 lần.
Odds Ratio cho PAY_02 (Trễ 2 tháng) = 7.1947764: Nguy cơ vỡ nợ tăng vọt, cao hơn gấp 7.2 lần.
Odds Ratio cho PAY_03+ (Trễ hạn nặng) = 7.061. Khả năng vỡ nợ vẫn ở mức rất cao, cao hơn gấp 7.1 lần.
Nhận xét: Kết quả này khẳng định mạnh mẽ rằng hành vi thanh toán của tháng gần nhất là yếu tố dự báo rủi ro quan trọng và trực tiếp nhất. Mức độ rủi ro tăng đáng kể theo từng cấp độ trễ hạn. Các biến PAY_k của các tháng trước đó (PAY_2 đến PAY_6) cũng cho thấy xu hướng tương tự, mặc dù ảnh hưởng có thể giảm dần theo thời gian.
Các biến Nhân khẩu học ổn định:
SEX2 (Nữ): Odds Ratio = 0.8785499. Sau khi kiểm soát các yếu tố khác, so với nhóm Nam (nhóm tham chiếu), khả năng vỡ nợ của nhóm Nữ thấp hơn khoảng 12.1%.
MARRIAGE2 (Độc thân): Odds Ratio = 0.8278215. So với nhóm Đã kết hôn (nhóm tham chiếu), khả năng vỡ nợ của nhóm Độc thân thấp hơn khoảng 17.2%.
EDUCATION4 (Học vấn Khác): Odds Ratio = 0.325. So với nhóm Sau Đại học (nhóm tham chiếu), khả năng vỡ nợ của nhóm này thấp hơn đáng kể.
Nhận xét: Các yếu tố nhân khẩu học có tác động có ý nghĩa thống kê và ổn định, nhưng mức độ ảnh hưởng (thay đổi dưới 20%) nhỏ hơn đáng kể so với các yếu tố hành vi thanh toán.
Các biến Tài chính và các khoản Thanh toán:
LIMIT_BAL và PAY_AMT1-6 (Hệ số âm): Dấu âm của hệ số là hoàn toàn hợp lý. Mặc dù tác động trên mỗi đơn vị tiền tệ là cực nhỏ, nhưng khi xem xét tổng thể, khách hàng có hạn mức tín dụng cao hơn đáng kể và số tiền thanh toán hàng tháng lớn hơn sẽ có rủi ro vỡ nợ thấp hơn.
Ví dụ minh họa: Giả sử hệ số hồi quy của LIMIT_BAL là −0.000001 và có ý nghĩa thống kê.
Sự khác biệt về hạn mức tín dụng giữa hai khách hàng là 100,000 Đài tệ.
Thay đổi trong log-odds vỡ nợ sẽ là: (−0.000001)×100,000=−0.1.
Khi chuyển đổi sang Odds Ratio (exp(-0.1)), ta được khoảng 0.905.
Điều này có nghĩa là, một khách hàng có hạn mức tín dụng cao hơn 100,000 Đài tệ sẽ có khả năng vỡ nợ thấp hơn khoảng 9.5% so với một khách hàng khác, sau khi các yếu tố khác được kiểm soát.
AVG_BILL_AMT (Hệ số dương): Tương tự, dấu dương cũng rất hợp lý. Khách hàng có số dư hóa đơn trung bình lớn hơn nhiều có xu hướng rủi ro vỡ nợ cao hơn. Mặc dù tác động trên từng đơn vị rất nhỏ, sự thay đổi lớn về số dư hóa đơn có thể làm tăng đáng kể khả năng vỡ nợ.
Nhận xét: Dấu của các hệ số này cho thấy một xu hướng hợp lý. Khách hàng có hạn mức tín dụng cao hơn và thực hiện các khoản thanh toán lớn hơn (PAY_AMT) có xu hướng rủi ro vỡ nợ thấp hơn. Ngược lại, việc có số dư hóa đơn trung bình cao hơn làm tăng nhẹ khả năng vỡ nợ. Mặc dù tác động trên mỗi đơn vị tiền tệ là rất nhỏ (do giá trị của các biến này rất lớn), nhưng tổng tác động khi xét đến toàn bộ giá trị của chúng là đáng kể.
Kết luận về mô hình:
Mô hình này cung cấp những hiểu biết sâu sắc và có giá trị về các yếu tố dự báo khả năng vỡ nợ, đặc biệt là tầm quan trọng vượt trội của hành vi thanh toán gần đây, cùng với vai trò của các yếu tố nhân khẩu học và tài chính khác. Mô hình này sẽ là cơ sở vững chắc cho các phân tích và dự báo tiếp theo.
Sau khi mô hình Logit cải thiện (model_logit_improved) được xây dựng, hiệu suất dự báo của nó được đánh giá một cách khách quan. Phân tích này sẽ so sánh hiệu suất trên cả tập huấn luyện và tập kiểm tra để kiểm tra khả năng tổng quát hóa và dấu hiệu của hiện tượng học quá khớp (overfitting).
Bảng 4.21 dưới đây hiển thị kết quả dự báo của mô hình Logit cải thiện cho 5 khách hàng đầu tiên trong tập kiểm tra. Bảng này so sánh giữa xác suất vỡ nợ được mô hình tính toán, quyết định phân loại cuối cùng (với ngưỡng 50%), và tình trạng vỡ nợ thực tế của họ.
Khách hàng ID (Mẫu) | Xác suất Vỡ nợ Dự báo | Dự báo Phân loại (Ngưỡng 50%) | Tình trạng Vỡ nợ Thực tế |
|---|---|---|---|
1 | 23.9% | 0 | 1 |
2 | 14.8% | 0 | 0 |
3 | 21.6% | 0 | 0 |
4 | 10.7% | 0 | 0 |
5 | 9.5% | 0 | 0 |
Nhận xét:
Bảng 4.20 minh họa cách mô hình hoạt động trong thực tế trên tập dữ liệu kiểm tra. Nó cho thấy sự khác biệt giữa dự báo xác suất (một thước đo rủi ro liên tục) và dự báo phân loại (một quyết định cuối cùng).
Trường hợp Dự báo Sai (False Negative): Đối với khách hàng mẫu số 1, mô hình đã tính toán xác suất vỡ nợ là 23.9%. Vì xác suất này nhỏ hơn ngưỡng quyết định 50%, mô hình đã đưa ra dự báo phân loại là ‘0’ (Không vỡ nợ). Tuy nhiên, tình trạng thực tế của khách hàng này lại là ‘1’ (Vỡ nợ). Đây là một ví dụ về sai lầm loại II (False Negative), nơi mô hình đã bỏ sót một trường hợp rủi ro.
Trường hợp Dự báo Đúng (True Negative): Đối với các khách hàng còn lại (mẫu số 2 đến 5), mô hình đã dự báo xác suất vỡ nợ rất thấp (từ 9.5% đến 14.8%). Do đó, chúng đều được phân loại là ‘0’ (Không vỡ nợ), hoàn toàn trùng khớp với tình trạng thực tế.
Ví dụ này cho thấy, trong khi mô hình có thể hoạt động hiệu quả với các trường hợp có rủi ro thấp rõ ràng, việc lựa chọn ngưỡng phân loại 50% có thể khiến nó trở nên quá “lạc quan” và bỏ lỡ các trường hợp có rủi ro ở mức trung bình. Hiệu suất tổng thể của mô hình trên toàn bộ 9,000 khách hàng của tập kiểm tra sẽ được tổng hợp và đánh giá chi tiết ở các phần tiếp theo, đặc biệt tập trung vào các chỉ số như Precision và Recall để có cái nhìn toàn diện hơn về khả năng xác định đúng các trường hợp vỡ nợ.
Để đánh giá tổng thể khả năng dự báo của mô hình, Bảng 4.21 dưới đây trình bày và so sánh các chỉ số hiệu suất chính trên cả hai tập dữ liệu huấn luyện và kiểm tra.
Chỉ số | Tập Huấn luyện (Train) | Tập Kiểm tra (Test) |
|---|---|---|
Độ chính xác (Accuracy) | 0.822 | 0.818 |
Độ chuẩn (Precision) | 0.686 | 0.669 |
Độ nhạy (Recall) | 0.359 | 0.353 |
F1-Score | 0.471 | 0.462 |
AUC | 0.774 | 0.761 |
Nhận xét:
Khả năng Tổng quát hóa tốt (Không Overfitting): Hiệu suất của mô hình trên tập huấn luyện và tập kiểm tra là rất tương đồng nhau. Ví dụ, chỉ số AUC trên tập huấn luyện là 0.774 và trên tập kiểm tra là 0.761. Sự khác biệt không đáng kể này là một dấu hiệu rất tích cực, cho thấy mô hình không bị phù hợp quá mức trên dữ liệu huấn luyện và có khả năng tổng quát hóa tốt khi áp dụng vào dữ liệu mới trong thực tế. Điều này đảm bảo rằng các kết luận về hiệu suất của mô hình là đáng tin cậy và không chỉ đúng trên tập dữ liệu đã học.
Sự Đánh đổi giữa Precision và Recall:
Mô hình đạt được Độ chuẩn (Precision) khá tốt trên tập kiểm tra (0.669). Điều này có nghĩa là khi mô hình dự báo một khách hàng sẽ vỡ nợ, dự báo đó có độ tin cậy cao, đúng trong khoảng 66.9% các trường hợp. Đây là một điểm mạnh nếu mục tiêu là giảm thiểu các “cảnh báo giả”.
Tuy nhiên, điểm yếu lớn nhất của mô hình nằm ở Độ nhạy (Recall), với giá trị rất thấp trên tập kiểm tra (0.353). Điều này cho thấy mô hình chỉ phát hiện được khoảng 35.3% trong tổng số các trường hợp vỡ nợ thực tế. Nói cách khác, mô hình đang bỏ sót một tỷ lệ lớn khách hàng rủi ro thực sự (False Negatives).
Ý nghĩa: Sự đánh đổi này là một bài toán kinh doanh cốt lõi. Một Recall thấp đồng nghĩa với rủi ro tổn thất tài chính cao do bỏ lỡ các khách hàng có khả năng vỡ nợ. Do đó, mặc dù mô hình có khả năng tổng quát hóa tốt, việc chỉ sử dụng ngưỡng quyết định mặc định 50% là chưa tối ưu và cần được cân nhắc điều chỉnh trong thực tế để tăng khả năng “bắt” được các trường hợp rủi ro. Việc điều chỉnh ngưỡng sẽ là một bước quan trọng để cân bằng giữa việc nhận diện đúng các trường hợp vỡ nợ và tránh các cảnh báo sai.
Để có một cái nhìn tổng thể về hiệu suất phân loại của mô hình mà không phụ thuộc vào một ngưỡng xác suất cụ thể nào, đường cong ROC (Receiver Operating Characteristic) và diện tích dưới đường cong (AUC) được sử dụng. Hình 4.4 so sánh đường cong ROC của mô hình trên cả hai tập dữ liệu huấn luyện và kiểm tra.
Hình 4.4: So sánh đường cong ROC trên tập huấn luyện và kiểm tra.
Nhận xét:
Không quá khớp (No Overfitting): Hai đường cong ROC của tập huấn luyện (màu đỏ) và tập kiểm tra (màu xanh) gần như chồng khít lên nhau. Điều này một lần nữa khẳng định kết luận từ Bảng 4.4 (Bảng So sánh hiệu suất) rằng mô hình không bị quá khớp với dữ liệu huấn luyện. Hiệu suất của mô hình trên dữ liệu đã thấy và dữ liệu mới là nhất quán, cho thấy khả năng tổng quát hóa tốt.
Khả năng phân loại: Giá trị AUC trên tập kiểm tra là 0.761. Theo quy ước, một giá trị AUC trong khoảng 0.7 đến 0.8 cho thấy mô hình có năng lực phân biệt ở mức khá tốt. Con số này có thể được diễn giải một cách trực quan rằng: nếu chọn ngẫu nhiên một khách hàng sẽ vỡ nợ và một khách hàng không vỡ nợ từ trong dữ liệu mới, có khoảng 76.1% khả năng mô hình sẽ gán một xác suất rủi ro cao hơn cho khách hàng thực sự vỡ nợ.
Kết luận tổng thể: Mặc dù chỉ số Recall ở ngưỡng 0.5 còn thấp (như đã phân tích ở phần trước), giá trị AUC cho thấy mô hình về tổng thể vẫn nắm bắt được các tín hiệu rủi ro quan trọng. Điều này chứng tỏ mô hình là một công cụ có giá trị trong việc phân loại và xếp hạng rủi ro của khách hàng, ngay cả khi cần điều chỉnh ngưỡng để tối ưu hóa việc phát hiện các trường hợp vỡ nợ.
Nghiên cứu đã đi đến một số kết luận cốt lõi, trả lời trực tiếp cho các câu hỏi nghiên cứu:
Về các yếu tố ảnh hưởng: Phân tích khẳng định
một cách mạnh mẽ rằng lịch sử hành vi tín dụng (đặc
biệt là tình trạng thanh toán của tháng gần nhất - PAY_0)
là nhóm yếu tố có sức ảnh hưởng quyết định đến khả năng vỡ nợ. Các yếu
tố nhân khẩu học và tài chính như hạn mức tín dụng, tình trạng hôn nhân
cũng có tác động có ý nghĩa, tuy nhiên mức độ ảnh hưởng thấp
hơn.
Về hiệu quả mô hình: Mô hình Hồi quy Logistic được xây dựng đã chứng tỏ được năng lực phân loại tổng thể ở mức khá tốt (AUC trên tập kiểm tra là 0.761), xác nhận tính hữu dụng của nó trong việc phân biệt khách hàng rủi ro. Tuy nhiên, mô hình cũng bộc lộ một sự đánh đổi (trade-off) quan trọng giữa Độ chuẩn (Precision ≈ 67%) và Độ nhạy (Recall ≈ 35%), cho thấy việc lựa chọn ngưỡng quyết định là một bài toán quản trị rủi ro quan trọng.
Các kết quả của nghiên cứu này có sự tương đồng cao với các công trình đi trước (Hand & Henley, 1997; Lee & Chen, 2005), củng cố thêm vai trò then chốt của hành vi thanh toán và vị thế của mô hình Logit như một công cụ nền tảng hiệu quả. Từ những phát hiện này, một số hàm ý thực tiễn có thể được rút ra:
Về Chiến lược Rủi ro: Phát hiện về sự đánh đổi giữa Precision và Recall cho thấy ngân hàng cần xác định rõ mức rủi ro của mình. Thay vì dùng một ngưỡng 50% cố định, ngân hàng có thể điều chỉnh ngưỡng này một cách linh hoạt: hạ thấp để tăng khả năng phát hiện rủi ro (tăng Recall) trong giai đoạn cần thắt chặt tín dụng, hoặc nâng cao để tối đa hóa phê duyệt (tăng Precision) trong giai đoạn muốn tăng trưởng.
Về Vận hành:
Nghiên cứu đã áp dụng thành công mô hình hồi quy logistic để phân tích bộ dữ liệu về vỡ nợ thẻ tín dụng, qua đó đạt được các mục tiêu đề ra. Đề tài đã xác định và lượng hóa được các yếu tố có ảnh hưởng ý nghĩa thống kê đến khả năng vỡ nợ, trong đó nổi bật là vai trò quyết định của lịch sử hành vi thanh toán. Mô hình được xây dựng cho thấy hiệu suất phân loại khá tốt và có khả năng tổng quát hóa, cung cấp một công cụ hữu ích cho việc dự báo rủi ro.
Về mặt thực tiễn, nghiên cứu đã đưa ra các hàm ý quan trọng cho các tổ chức tín dụng trong việc cải tiến hệ thống chấm điểm, quản lý danh mục và xây dựng chiến lược rủi ro. Về mặt học thuật, đề tài cung cấp một ví dụ chi tiết và chuẩn mực về quy trình phân tích dữ liệu định tính bằng phần mềm R.
Mặc dù đã đạt được các mục tiêu chính, nghiên cứu vẫn còn một số hạn chế cần được nhìn nhận. Về dữ liệu, tính thời điểm của bộ dữ liệu (2005) và sự thiếu vắng các biến quan trọng như thu nhập là những rào cản cho việc áp dụng trực tiếp. Về phương pháp, nghiên cứu chỉ tập trung vào mô hình Logistic và chưa đi sâu vào việc tối ưu hóa ngưỡng quyết định.
Từ những hạn chế này, các hướng nghiên cứu trong tương lai có thể được phát triển:
Mở rộng bộ dữ liệu: Áp dụng các phương pháp tương tự trên các bộ dữ liệu mới hơn và đầy đủ hơn, đặc biệt tại thị trường Việt Nam.
So sánh các phương pháp mô hình hóa: Thực hiện một nghiên cứu so sánh hiệu suất giữa mô hình Logistic và các thuật toán học máy hiện đại (Random Forest, XGBoost).
Phân tích sâu hơn về hành vi: Tập trung vào kỹ thuật đặc trưng (feature engineering) để tạo ra các biến mới có sức mạnh dự báo cao hơn từ dữ liệu gốc.
Trần Mạnh Tường (2025), Giáo trình Phân tích Dữ liệu Định tính.
Altman, E. I. (1968). Financial Ratios, Discriminant Analysis and the Prediction of Corporate Bankruptcy. The Journal of Finance, 23(4), 589–609.
Hand, D. J., & Henley, W. E. (1997). Statistical classification methods in consumer credit scoring: a review. Journal of the Royal Statistical Society: Series A (Statistics in Society), 160(3), 523-541.
Lee, T. S., & Chen, I. F. (2005). A two-stage hybrid credit scoring model using artificial neural networks and multivariate adaptive regression splines. Expert Systems with Applications, 28(4), 743-752.
Limsombunchai, V., Gan, C., & Lee, M. (2004). An analysis of credit scoring for agricultural loans in Thailand. American Journal of Applied Sciences, 1(3), 191-199.
Thomas, L. C. (2009). Consumer credit models: Pricing, profit and portfolios. Oxford University Press.
Yeh, I. C., & Chi, C. H. (2009). Comparisons of credit scoring models using support vector machines and multivariate discriminant analysis. Expert Systems with Applications, 36(2), 2473-2477.
# 1. TẢI CÁC THƯ VIỆN CẦN THIẾT
knitr::opts_chunk$set(echo = TRUE, warning = FALSE, message = FALSE)
library(tidyverse); library(readxl); library(knitr); library(flextable)
library(caTools); library(pROC); library(broom); library(car)
# 2. ĐỌC VÀ LÀM SẠCH DỮ LIỆU BAN ĐẦU
duong_dan_file <- "/Users/hotranhongnga/Downloads/UFM/HK2-2025/Phân tích dữ liệu định tính/Tiểu luận/credit_data.xls"
credit_df <- read_excel(duong_dan_file, skip = 1)
# Làm sạch cơ bản
credit_df$ID <- NULL
credit_df$EDUCATION[credit_df$EDUCATION %in% c(0, 5, 6)] <- 4
credit_df$MARRIAGE[credit_df$MARRIAGE == 0] <- 3
credit_df <- credit_df %>%
rename(default_payment_next_month = `default payment next month`)
# 3. XỬ LÝ DỮ LIỆU
pay_cols <- c("PAY_0", "PAY_2", "PAY_3", "PAY_4", "PAY_5", "PAY_6")
bill_amt_cols <- c("BILL_AMT1", "BILL_AMT2", "BILL_AMT3", "BILL_AMT4", "BILL_AMT5", "BILL_AMT6")
credit_df_final <- credit_df %>%
# Xử lý hạng mục hiếm
mutate(across(all_of(pay_cols), ~ case_when(
.x <= 0 ~ as.character(.x),
.x == 1 ~ "1",
.x == 2 ~ "2",
.x >= 3 ~ "3+"
))) %>%
# Xử lý đa cộng tuyến
mutate(AVG_BILL_AMT = rowMeans(dplyr::select(., all_of(bill_amt_cols)), na.rm = TRUE)) %>%
dplyr::select(-all_of(bill_amt_cols)) %>%
# Chuyển đổi factor
mutate(
default_payment_next_month = as.factor(default_payment_next_month),
SEX = as.factor(SEX),
EDUCATION = as.factor(EDUCATION),
MARRIAGE = as.factor(MARRIAGE),
across(all_of(pay_cols), ~ factor(.x, levels = c("-2", "-1", "0", "1", "2", "3+")))
)
# 4. CHIA DỮ LIỆU CUỐI CÙNG
set.seed(123)
split <- sample.split(credit_df_final$default_payment_next_month, SplitRatio = 0.7)
train_set <- subset(credit_df_final, split == TRUE)
test_set <- subset(credit_df_final, split == FALSE)
cat("```\n")
capture.output(str(credit_df), file = stdout())
cat("```\n")
library(dplyr)
library(flextable)
# Kiểm tra xem credit_df đã được tải chưa
if (!exists("credit_df")) {
stop("Đối tượng 'credit_df' chưa tồn tại. Vui lòng chạy các chunk trước đó để tải dữ liệu.")
}
credit_df %>%
head() %>%
flextable(
col_keys = c("LIMIT_BAL", "SEX", "EDUCATION", "MARRIAGE", "AGE",
"PAY_0", "PAY_2", "PAY_3", "PAY_4", "PAY_5", "PAY_6",
"BILL_AMT1", "BILL_AMT2", "BILL_AMT3", "BILL_AMT4", "BILL_AMT5", "BILL_AMT6",
"PAY_AMT1", "PAY_AMT2", "PAY_AMT3", "PAY_AMT4", "PAY_AMT5", "PAY_AMT6",
"default_payment_next_month") # Đảm bảo tất cả các cột đều được hiển thị
) %>%
set_caption("Bảng 3.1: 6 dòng dữ liệu đầu tiên của bộ dữ liệu gốc") %>%
autofit()
library(flextable)
library(readxl)
library(dplyr)
duong_dan_file <- "/Users/hotranhongnga/Downloads/UFM/HK2-2025/Phân tích dữ liệu định tính/Tiểu luận/credit_data.xls"
temp_credit_df <- read_excel(duong_dan_file, skip = 1)
# Đổi tên cột và bỏ cột ID
temp_credit_df <- temp_credit_df %>%
dplyr::rename(default_payment_next_month = `default payment next month`) %>%
dplyr::select(-ID)
# 2. TẠO DATA FRAME MÔ TẢ
mota_bien_day_du <- data.frame(
`STT` = 1:24,
`Tên biến` = names(temp_credit_df),
`Diễn giải` = c(
"Hạn mức tín dụng được cấp (đơn vị: Đài tệ)",
"Giới tính (1 = Nam, 2 = Nữ)",
"Trình độ học vấn (1 = Sau đại học, 2 = Đại học, 3 = Trung học phổ thông, 4 = Khác)",
"Tình trạng hôn nhân (1 = Kết hôn, 2 = Độc thân, 3 = Khác)",
"Tuổi (năm)",
"Tình trạng trả nợ tháng 9/2005 (-2 = trả đúng hạn và chưa phát sinh chi tiêu, -1 = trả đúng hạn, 0 = quay vòng tín dụng, 1 = trễ 1 tháng, ..., 9 = trễ 9 tháng trở lên)",
"Tình trạng trả nợ tháng 8/2005",
"Tình trạng trả nợ tháng 7/2005",
"Tình trạng trả nợ tháng 6/2005",
"Tình trạng trả nợ tháng 5/2005",
"Tình trạng trả nợ tháng 4/2005",
"Số tiền sao kê tháng 9/2005 (đơn vị: Đài tệ)",
"Số tiền sao kê tháng 8/2005",
"Số tiền sao kê tháng 7/2005",
"Số tiền sao kê tháng 6/2005",
"Số tiền sao kê tháng 5/2005",
"Số tiền sao kê tháng 4/2005",
"Khoản thanh toán trước đó vào tháng 9/2005 (đơn vị: Đài tệ)",
"Khoản thanh toán trước đó vào tháng 8/2005",
"Khoản thanh toán trước đó vào tháng 7/2005",
"Khoản thanh toán trước đó vào tháng 6/2005",
"Khoản thanh toán trước đó vào tháng 5/2005",
"Khoản thanh toán trước đó vào tháng 4/2005",
"Biến mục tiêu: Khả năng vỡ nợ tháng tới (1 = Có vỡ nợ, 0 = Không vỡ nợ)"
),
`Thang đo` = c(
"Định lượng", "Định tính", "Định tính", "Định tính", "Định lượng",
rep("Định tính (Thứ bậc)", 6),
rep("Định lượng", 6),
rep("Định lượng", 6),
"Định tính (Nhị phân)"
),
check.names = FALSE
)
# 3. TRÌNH BÀY BẢNG
flextable(mota_bien_day_du) %>%
set_caption("Bảng 3.2: Mô tả chi tiết các biến trong bộ dữ liệu nghiên cứu.") %>%
autofit() %>%
width(j = "Diễn giải", width = 4) %>%
theme_booktabs()
library(flextable); library(broom); library(dplyr); library(ggplot2)
# 1. TÍNH TOÁN
freq_table_eda <- table(train_set$default_payment_next_month)
prop_table_eda <- prop.table(freq_table_eda)
so_luong_vo_no_eda <- freq_table_eda["1"]
tong_so_quan_sat_eda <- sum(freq_table_eda)
ty_le_vo_no_mau_eda <- prop_table_eda["1"]
test_result_eda <- prop.test(x = so_luong_vo_no_eda, n = tong_so_quan_sat_eda, p = 0.20, conf.level = 0.95)
p_value_prop_test_eda <- test_result_eda$p.value
conf_int_lower_eda <- round(test_result_eda$conf.int[1] * 100, 2)
conf_int_upper_eda <- round(test_result_eda$conf.int[2] * 100, 2)
# Chuẩn bị bảng phân phối
result_df_display_eda <- data.frame(
"Tình trạng" = c("Không vỡ nợ (0)", "Vỡ nợ (1)"),
"Số lượng" = as.integer(freq_table_eda),
"Tỷ lệ (%)" = round(as.numeric(prop_table_eda) * 100, 2),
check.names = FALSE
)
# 2. TRÌNH BÀY BẢNG 4.1
flextable(result_df_display_eda) %>%
set_caption("Bảng 4.1: Phân phối của biến phụ thuộc trên tập huấn luyện.") %>%
autofit()
# 3. TRÌNH BÀY BIỂU ĐỒ HÌNH 4.1
ggplot(result_df_display_eda, aes(x = `Tình trạng`, y = `Số lượng`, fill = `Tình trạng`)) +
geom_bar(stat = "identity", show.legend = FALSE) +
geom_text(aes(label = paste0(`Tỷ lệ (%)`, "%")), vjust = -0.5, size = 4) +
labs(title = "Phân phối khách hàng theo Tình trạng Vỡ nợ",
x = "Tình trạng Vỡ nợ", y = "Số lượng khách hàng") +
theme_minimal() +
scale_y_continuous(labels = scales::comma)
# 4. TRÌNH BÀY BẢNG 4.2
tidy_test_result_eda <- tidy(test_result_eda) %>%
mutate(p.value.display = ifelse(p.value < 0.001, "<0.001", format(round(p.value, 3), nsmall = 3))) %>%
dplyr::select(estimate, statistic, p.value.display, parameter, conf.low, conf.high)
flextable(tidy_test_result_eda) %>%
set_header_labels(
estimate = "Tỷ lệ mẫu (Vỡ nợ)", statistic = "Giá trị Chi-bình phương",
p.value.display = "P-value", parameter = "Bậc tự do",
conf.low = "Giới hạn dưới KTC 95%", conf.high = "Giới hạn trên KTC 95%"
) %>%
colformat_double(j = c("estimate", "statistic", "conf.low", "conf.high"), digits = 4) %>%
set_caption("Bảng 4.2: Kết quả kiểm định giả thuyết về tỷ lệ vỡ nợ trên tập huấn luyện.") %>%
autofit()
library(flextable); library(dplyr); library(tidyr)
if (!exists("train_set")) {
stop("Biến 'train_set' chưa được định nghĩa. Vui lòng chạy lại khối 'setup'.")
}
# Tính toán cho từng biến từ train_set và gộp lại
sex_df_eda <- data.frame(table(train_set$SEX)) %>%
mutate(Bien = "Giới tính", Nhan = c("Nam", "Nữ"))
edu_df_eda <- data.frame(table(train_set$EDUCATION)) %>%
mutate(Bien = "Học vấn", Nhan = c("Sau ĐH", "Đại học", "THPT", "Khác"))
mrg_df_eda <- data.frame(table(train_set$MARRIAGE)) %>%
mutate(Bien = "Hôn nhân", Nhan = c("Đã kết hôn", "Độc thân", "Khác"))
# Gộp các data frame lại
demographics_summary_eda <- bind_rows(sex_df_eda, edu_df_eda, mrg_df_eda) %>%
rename(PhanLoai = Nhan, SoLuong = Freq) %>%
group_by(Bien) %>%
mutate(TyLe_PhanTram = round(SoLuong / sum(SoLuong) * 100, 1)) %>%
ungroup() %>%
dplyr::select(Bien, PhanLoai, SoLuong, TyLe_PhanTram)
# Trình bày bảng
flextable(demographics_summary_eda) %>%
set_header_labels(
Bien = "Biến",
PhanLoai = "Phân loại",
SoLuong = "Số lượng",
TyLe_PhanTram = "Tỷ lệ (%)"
) %>%
set_caption("Bảng 4.3: Phân phối khách hàng theo các đặc điểm nhân khẩu học trên tập huấn luyện.") %>%
merge_v(j = "Bien") %>%
fix_border_issues() %>%
autofit() %>%
theme_booktabs()
# TRỰC QUAN HÓA BẰNG BIỂU ĐỒ
library(ggplot2)
ggplot(demographics_summary_eda, aes(x = PhanLoai, y = SoLuong, fill = Bien)) +
geom_bar(stat = "identity", show.legend = FALSE) +
facet_wrap(~ Bien, scales = "free_x") +
geom_text(aes(label = format(SoLuong, big.mark = ",")), vjust = -0.5, size = 3) +
labs(title = "Phân phối khách hàng theo các đặc điểm Nhân khẩu học", x = NULL, y = "Số lượng khách hàng") +
theme_minimal(base_size = 10) +
theme(axis.text.x = element_text(angle = 15, hjust = 1))
# TẠO BẢNG TÓM TẮT CHO BIẾN ĐỊNH LƯỢNG
if (!exists("train_set")) {
stop("Biến 'train_set' chưa được định nghĩa. Vui lòng chạy lại khối 'setup'.")
}
summary_stats_eda <- data.frame(
`Thống kê` = c("Trung bình", "Độ lệch chuẩn", "Trung vị", "Giá trị nhỏ nhất", "Giá trị lớn nhất"),
`Hạn mức tín dụng (LIMIT_BAL)` = c(
mean(train_set$LIMIT_BAL), sd(train_set$LIMIT_BAL), median(train_set$LIMIT_BAL),
min(train_set$LIMIT_BAL), max(train_set$LIMIT_BAL)
),
`Tuổi (AGE)` = c(
mean(train_set$AGE), sd(train_set$AGE), median(train_set$AGE),
min(train_set$AGE), max(train_set$AGE)
),
check.names = FALSE
)
# Trình bày bảng
flextable(summary_stats_eda) %>%
colformat_double(j = 2:3, digits = 0, big.mark = ",") %>%
set_caption("Bảng 4.4: Thống kê mô tả cho các biến định lượng trên tập huấn luyện.") %>%
autofit() %>%
theme_booktabs()
# PHÂN TÍCH HAI BIẾN
library(flextable); library(dplyr); library(broom)
analyze_categorical_vs_default <- function(variable_name, group_labels, comparison_group, reference_group) {
cross_table <- table(train_set[[variable_name]], train_set$default_payment_next_month)
cross_df <- as.data.frame.matrix(cross_table); colnames(cross_df) <- c("Không vỡ nợ", "Vỡ nợ")
cross_df <- cross_df %>%
mutate(Nhom = group_labels, TongSo = `Không vỡ nợ` + `Vỡ nợ`, TyLeVoNo = round((`Vỡ nợ`/TongSo)*100, 1)) %>%
dplyr::select(Nhom, `Không vỡ nợ`, `Vỡ nợ`, TongSo, TyLeVoNo)
a <- cross_df$`Vỡ nợ`[cross_df$Nhom == comparison_group]; b <- cross_df$`Không vỡ nợ`[cross_df$Nhom == comparison_group]
c <- cross_df$`Vỡ nợ`[cross_df$Nhom == reference_group]; d <- cross_df$`Không vỡ nợ`[cross_df$Nhom == reference_group]
rr <- (a/(a+b)) / (c/(c+d)); or <- (a/b) / (c/d)
rr_or_table <- data.frame(Thuoc_do = c("Rủi ro Tương đối (RR)", "Tỷ lệ chênh (OR)"), Gia_tri = c(rr, or))
chi_test <- tidy(chisq.test(cross_table)) %>%
mutate(p.value.display = ifelse(p.value < 0.001, "<0.001", format(round(p.value, 3), nsmall = 3))) %>%
dplyr::select(statistic, p.value.display, parameter, method)
return(list(crosstab = cross_df, rr_or = rr_or_table, chi_test = chi_test))
}
edu_analysis <- analyze_categorical_vs_default("EDUCATION", c("Sau ĐH", "Đại học", "THPT", "Khác"), "THPT", "Sau ĐH")
sex_analysis <- analyze_categorical_vs_default("SEX", c("Nam", "Nữ"), "Nam", "Nữ")
mrg_analysis <- analyze_categorical_vs_default("MARRIAGE", c("Đã kết hôn", "Độc thân", "Khác"), "Đã kết hôn", "Độc thân")
flextable(edu_analysis$crosstab) %>% set_caption("Bảng 4.5: Bảng chéo giữa Học vấn và Tình trạng vỡ nợ.") %>% autofit() %>% theme_booktabs()
flextable(edu_analysis$rr_or) %>% set_caption("Bảng 4.6: So sánh rủi ro giữa nhóm THPT và Sau Đại học.") %>% colformat_double(j=2, digits=2) %>% autofit() %>% theme_booktabs()
flextable(edu_analysis$chi_test) %>% set_header_labels(statistic = "Giá trị (χ²)", p.value.display = "P-value", parameter = "df", method = "Phương pháp") %>% colformat_double(j=1, digits=3) %>% set_caption("Bảng 4.7: Kết quả kiểm định Chi-bình phương cho Học vấn.") %>% autofit() %>% theme_booktabs()
flextable(sex_analysis$crosstab) %>% set_caption("Bảng 4.8: Bảng chéo giữa Giới tính và Tình trạng vỡ nợ.") %>% autofit() %>% theme_booktabs()
flextable(sex_analysis$rr_or) %>% set_caption("Bảng 4.9: So sánh rủi ro giữa nhóm Nam và Nữ.") %>% colformat_double(j=2, digits=2) %>% autofit() %>% theme_booktabs()
flextable(sex_analysis$chi_test) %>% set_header_labels(statistic = "Giá trị (χ²)", p.value.display = "P-value", parameter = "df", method = "Phương pháp") %>% colformat_double(j=1, digits=3) %>% set_caption("Bảng 4.10: Kết quả kiểm định Chi-bình phương cho Giới tính.") %>% autofit() %>% theme_booktabs()
flextable(mrg_analysis$crosstab) %>% set_caption("Bảng 4.11: Bảng chéo giữa Tình trạng hôn nhân và Vỡ nợ.") %>% autofit() %>% theme_booktabs()
flextable(mrg_analysis$rr_or) %>% set_caption("Bảng 4.12: So sánh rủi ro giữa nhóm Đã kết hôn và Độc thân.") %>% colformat_double(j=2, digits=2) %>% autofit() %>% theme_booktabs()
flextable(mrg_analysis$chi_test) %>% set_header_labels(statistic = "Giá trị (χ²)", p.value.display = "P-value", parameter = "df", method = "Phương pháp") %>% colformat_double(j=1, digits=3) %>% set_caption("Bảng 4.13: Kết quả kiểm định Chi-bình phương cho Tình trạng hôn nhân.") %>% autofit() %>% theme_booktabs()
# TRỰC QUAN HÓA LIMIT_BAL
library(ggplot2)
if (!exists("train_set")) {
stop("Biến 'train_set' chưa được định nghĩa. Vui lòng chạy lại khối 'setup'.")
}
median_limit_bal_0 <- median(train_set$LIMIT_BAL[train_set$default_payment_next_month == 0])
median_limit_bal_1 <- median(train_set$LIMIT_BAL[train_set$default_payment_next_month == 1])
ggplot(train_set, aes(x = default_payment_next_month, y = LIMIT_BAL, fill = default_payment_next_month)) +
geom_boxplot(show.legend = FALSE, outlier.alpha = 0.1) +
scale_y_continuous(labels = scales::comma) +
labs(title = "So sánh hạn mức tín dụng giữa hai nhóm vỡ nợ",
x = "Tình trạng vỡ nợ (0: Không, 1: Có)",
y = "Hạn mức tín dụng (Đài tệ)") +
theme_minimal()
# PHÂN TÍCH CHO BIẾN PAY_0
library(flextable); library(dplyr); library(broom)
if (!exists("train_set")) {
stop("Biến 'train_set' chưa được định nghĩa. Vui lòng chạy lại khối 'setup'.")
}
# 1. TẠO BẢNG CHÉO
cross_table_pay0 <- table(train_set$PAY_0, train_set$default_payment_next_month)
cross_df_pay0 <- as.data.frame.matrix(cross_table_pay0)
colnames(cross_df_pay0) <- c("Không vỡ nợ", "Vỡ nợ")
cross_df_pay0 <- cross_df_pay0 %>%
mutate(
TrangThai = rownames(cross_df_pay0),
TongSo = `Không vỡ nợ` + `Vỡ nợ`,
TyLeVoNo = round((`Vỡ nợ` / TongSo) * 100, 1)
) %>%
dplyr::select(TrangThai, `Không vỡ nợ`, `Vỡ nợ`, TongSo, TyLeVoNo)
# 2. TÍNH RR VÀ OR (Trễ 1 tháng vs Trả đủ tối thiểu làm tham chiếu)
# Đảm bảo các mức '1' và '0' tồn tại trong PAY_0 sau khi xử lý factor
# Nếu không tồn tại, có thể cần điều chỉnh để tránh lỗi
if ("1" %in% rownames(cross_table_pay0) && "0" %in% rownames(cross_table_pay0)) {
a <- cross_table_pay0["1", "1"]; b <- cross_table_pay0["1", "0"]
c <- cross_table_pay0["0", "1"]; d <- cross_table_pay0["0", "0"]
risk_delay1 <- a/(a+b)
risk_ontime <- c/(c+d)
# Tránh chia cho 0 nếu mẫu bằng 0
odds_delay1 <- if(b == 0) Inf else a/b
odds_ontime <- if(d == 0) Inf else c/d
relative_risk_pay0 <- risk_delay1 / risk_ontime
odds_ratio_pay0 <- odds_delay1 / odds_ontime
rr_or_table_pay0 <- data.frame(
Thuoc_do = c("Rủi ro Tương đối (RR)", "Tỷ lệ chênh (OR)"),
Gia_tri = c(relative_risk_pay0, odds_ratio_pay0)
)
} else {
rr_or_table_pay0 <- data.frame(
Thuoc_do = c("Rủi ro Tương đối (RR)", "Tỷ lệ chênh (OR)"),
Gia_tri = c(NA, NA)
)
warning("Không tìm thấy đủ các mức '1' hoặc '0' trong PAY_0 để tính RR/OR.")
}
# 3. KIỂM ĐỊNH CHI-BÌNH PHƯƠNG
chi_test_pay0 <- tidy(chisq.test(cross_table_pay0)) %>%
mutate(p.value.display = ifelse(p.value < 0.001, "<0.001", format(round(p.value, 3), nsmall = 3))) %>%
dplyr::select(statistic, p.value.display, parameter, method)
flextable(cross_df_pay0) %>%
set_header_labels(
TrangThai = "Trạng thái",
TyLeVoNo = "Tỷ lệ vỡ nợ (%)"
) %>%
set_caption("Bảng 4.14: Bảng chéo giữa Tình trạng thanh toán gần nhất và Vỡ nợ.") %>%
autofit() %>%
theme_booktabs()
flextable(rr_or_table_pay0) %>%
set_caption("Bảng 4.15: So sánh rủi ro giữa nhóm Trễ hạn 1 tháng và Thanh toán đủ mức tối thiểu.") %>%
colformat_double(j=2, digits=2) %>%
autofit() %>%
theme_booktabs()
# KIỂM TRA ĐA CỘNG TUYẾN
library(car); library(dplyr); library(flextable)
if (!exists("train_set")) {
stop("Biến 'train_set' chưa được định nghĩa. Vui lòng chạy lại khối 'setup'.")
}
temp_credit_df_for_vif <- credit_df %>%
dplyr::select_if(is.numeric) %>%
dplyr::select(LIMIT_BAL, BILL_AMT1, BILL_AMT2, BILL_AMT3, BILL_AMT4, BILL_AMT5, BILL_AMT6,
PAY_AMT1, PAY_AMT2, PAY_AMT3, PAY_AMT4, PAY_AMT5, PAY_AMT6, AGE)
# Lấy các biến số numeric để đưa vào mô hình VIF ban đầu
numeric_var_names_initial <- names(temp_credit_df_for_vif)
temp_y_var_initial <- "AGE"
temp_x_vars_initial <- numeric_var_names_initial[numeric_var_names_initial != temp_y_var_initial]
# Kiểm tra nếu có đủ biến để tạo công thức
if (length(temp_x_vars_initial) == 0) {
stop("Không đủ biến định lượng để thực hiện kiểm tra VIF ban đầu.")
}
formula_initial <- as.formula(paste(temp_y_var_initial, "~", paste(temp_x_vars_initial, collapse = " + ")))
# Xây dựng mô hình hồi quy tuyến tính để tính VIF
vif_model_initial <- lm(formula_initial, data = temp_credit_df_for_vif, na.action = na.omit)
vif_scores_initial <- vif(vif_model_initial)
vif_df_initial <- data.frame(`Biến số` = names(vif_scores_initial), VIF = vif_scores_initial, check.names = FALSE) %>% arrange(desc(VIF))
# 2. KIỂM TRA LẠI TRÊN DỮ LIỆU ĐÃ XỬ LÝ
numeric_vars_processed <- train_set %>% dplyr::select_if(is.numeric)
numeric_var_names_processed <- names(numeric_vars_processed)
temp_y_var_processed <- "AGE"
temp_x_vars_processed <- numeric_var_names_processed[numeric_var_names_processed != temp_y_var_processed]
if (length(temp_x_vars_processed) == 0) {
stop("Không đủ biến định lượng để thực hiện kiểm tra VIF sau xử lý.")
}
formula_processed <- as.formula(paste(temp_y_var_processed, "~", paste(temp_x_vars_processed, collapse = " + ")))
vif_model_processed <- lm(formula_processed, data = numeric_vars_processed, na.action = na.omit)
vif_scores_processed <- vif(vif_model_processed)
vif_df_processed <- data.frame(`Biến số` = names(vif_scores_processed), VIF = vif_scores_processed, check.names = FALSE) %>% arrange(desc(VIF))
flextable(vif_df_initial) %>%
set_caption("Bảng 4.16: Kết quả kiểm tra Đa cộng tuyến ban đầu.") %>%
colformat_double(j = "VIF", digits = 3) %>%
autofit() %>%
theme_booktabs()
flextable(vif_df_processed) %>%
set_caption("Bảng 4.17: Kết quả kiểm tra Đa cộng tuyến sau khi xử lý.") %>%
colformat_double(j = "VIF", digits = 3) %>%
autofit() %>%
theme_booktabs()
# XÂY DỰNG VÀ SO SÁNH 3 MÔ HÌNH TRÊN DỮ LIỆU ĐÃ XỬ LÝ
library(flextable); library(dplyr); library(broom)
if (!exists("train_set")) {
stop("Biến 'train_set' chưa được định nghĩa. Vui lòng chạy lại khối 'setup'.")
}
# 1. XÂY DỰNG 3 MÔ HÌNH
model_logit <- glm(default_payment_next_month ~ ., data = train_set, family = binomial(link = "logit"))
model_probit <- glm(default_payment_next_month ~ ., data = train_set, family = binomial(link = "probit"))
model_cloglog <- glm(default_payment_next_month ~ ., data = train_set, family = binomial(link = "cloglog"))
# 2. LẤY CHỈ SỐ AIC ĐỂ SO SÁNH
aic_values <- data.frame(
`Mô hình` = c("Logit (Hồi quy Logistic)", "Probit (Hồi quy Probit)", "Cloglog (Complementary Log-log)"),
AIC = c(AIC(model_logit), AIC(model_probit), AIC(model_cloglog)),
check.names = FALSE
) %>% arrange(AIC)
# 3. CHUẨN BỊ BẢNG KẾT QUẢ CHO MÔ HÌNH LOGIT (Được chọn)
results_logit <- tidy(model_logit) %>%
mutate(
odds_ratio = exp(estimate),
p.value.display = ifelse(p.value < 0.001, "<0.001", format(round(p.value, 3), nsmall = 3))
)
# TRÌNH BÀY BẢNG SO SÁNH AIC
flextable(aic_values) %>%
set_caption("Bảng 4.18: So sánh chỉ số AIC của các mô hình.") %>%
colformat_double(j = "AIC", digits = 2, big.mark = ",") %>%
autofit() %>%
theme_booktabs()
# XỬ LÝ DỮ LIỆU VÀ XÂY DỰNG LẠI MÔ HÌNH
library(flextable); library(broom); library(dplyr)
if (!exists("train_set")) {
stop("Biến 'train_set' chưa được định nghĩa. Vui lòng chạy lại khối 'setup'.")
}
# 1. TẠO MỘT BẢN SAO CỦA train_set
# đảm bảo không ghi đè lên đối tượng gốc 'train_set'
train_set_temp <- train_set
# 2. XỬ LÝ TẤT CẢ CÁC BIẾN PAY_
pay_cols <- c("PAY_0", "PAY_2", "PAY_3", "PAY_4", "PAY_5", "PAY_6")
for (col in pay_cols) {
col_char <- as.character(train_set_temp[[col]])
new_values <- case_when(
col_char == "-2" ~ "-2",
col_char == "-1" ~ "-1",
col_char == "0" ~ "0",
col_char == "1" ~ "1",
col_char == "2" ~ "2",
TRUE ~ "3+" # Gộp tất cả các giá trị còn lại (>=3) thành "3+"
)
# Chuyển đổi lại thành factor với các cấp độ đã định nghĩa
train_set_temp[[col]] <- factor(new_values, levels = c("-2", "-1", "0", "1", "2", "3+"))
}
# 3. XÂY DỰNG MÔ HÌNH CẢI THIỆN TRÊN DỮ LIỆU ĐÃ XỬ LÝ
model_logit_improved <- glm(default_payment_next_month ~ ., data = train_set_temp, family = binomial(link = "logit"))
# 4. CHUẨN BỊ BẢNG KẾT QUẢ MỚI
results_logit_improved <- tidy(model_logit_improved) %>%
mutate(
odds_ratio = exp(estimate),
p.value.display = ifelse(p.value < 0.001, "<0.001", format(round(p.value, 3), nsmall = 3))
)
# Trình bày bảng kết quả của mô hình mới
flextable(results_logit_improved[, c("term", "estimate", "std.error", "p.value.display", "odds_ratio")]) %>%
set_header_labels(
term = "Biến số", estimate = "Hệ số (β)", std.error = "Sai số chuẩn",
p.value.display = "P-value", odds_ratio = "Odds Ratio"
) %>%
colformat_double(j = c("estimate", "std.error"), digits = 4) %>%
colformat_double(j = "odds_ratio", digits = 3, big.mark = ",") %>%
align(j = "term", align = "left") %>%
align(j = 2:5, align = "center", part = "all") %>%
set_caption("Bảng 4.19: Kết quả ước lượng của mô hình Logit.") %>%
autofit() %>%
theme_booktabs()
# XÂY DỰNG VÀ ĐÁNH GIÁ MÔ HÌNH
# Tải các thư viện cần thiết
library(pROC)
library(ggplot2)
library(flextable)
library(dplyr)
library(broom)
# 1. KIỂM TRA SỰ TỒN TẠI CỦA DỮ LIỆU GỐC VÀ CÁC BIẾN PAY_X
if (!exists("train_set") || !exists("test_set")) {
stop("Các biến 'train_set' hoặc 'test_set' chưa được định nghĩa. Vui lòng chạy lại khối 'setup' chứa dữ liệu gốc.")
}
pay_cols <- c("PAY_0", "PAY_2", "PAY_3", "PAY_4", "PAY_5", "PAY_6")
target_pay_levels <- c("-2", "-1", "0", "1", "2", "3+")
# Hàm để xử lý an toàn các cột PAY_x
process_pay_column <- function(data_col, levels_list) {
# Chuyển đổi giá trị về ký tự để case_when có thể xử lý đúng
val_char <- as.character(data_col)
# Áp dụng logic gộp nhóm
grouped_val <- case_when(
val_char == "-2" ~ "-2",
val_char == "-1" ~ "-1",
val_char == "0" ~ "0",
val_char == "1" ~ "1",
val_char == "2" ~ "2",
TRUE ~ "3+" # Gộp tất cả các giá trị khác (tức >=3) thành "3+"
)
factor(grouped_val, levels = levels_list)
}
# Áp dụng xử lý cho TẬP HUẤN LUYỆN
train_set_final <- train_set %>%
mutate(across(all_of(pay_cols), ~process_pay_column(.x, target_pay_levels)))
# Áp dụng xử lý cho TẬP KIỂM TRA
test_set_final <- test_set %>%
mutate(across(all_of(pay_cols), ~process_pay_column(.x, target_pay_levels)))
# 1.5: ĐẢM BẢO TẤT CẢ CÁC CẤP ĐỘ ĐƯỢC MÔ HÌNH GLM "NHÌN THẤY" (PHẦN MỚI BỔ SUNG)
# Tạo một dataframe giả (dummy dataframe) chứa TẤT CẢ các cấp độ của biến factor PAY_x.
dummy_data_for_levels <- data.frame(
matrix(NA, nrow = length(target_pay_levels), ncol = length(pay_cols))
)
colnames(dummy_data_for_levels) <- pay_cols
for(col in pay_cols) {
dummy_data_for_levels[[col]] <- factor(target_pay_levels, levels = target_pay_levels)
}
other_cols <- setdiff(names(train_set_final), c(pay_cols, "default_payment_next_month"))
for (col in other_cols) {
if (is.numeric(train_set_final[[col]])) {
dummy_data_for_levels[[col]] <- 0
} else if (is.factor(train_set_final[[col]])) {
dummy_data_for_levels[[col]] <- factor(levels(train_set_final[[col]])[1], levels = levels(train_set_final[[col]]))
} else {
dummy_data_for_levels[[col]] <- NA
}
}
# Đảm bảo biến mục tiêu cũng là factor và có ít nhất 1 cấp độ
dummy_data_for_levels$default_payment_next_month <- factor(
levels(train_set_final$default_payment_next_month)[1], # Gán mức đầu tiên
levels = levels(train_set_final$default_payment_next_month)
)
# Kết hợp train_set_final với dummy_data_for_levels.
train_set_with_dummies <- bind_rows(train_set_final, dummy_data_for_levels)
# 2. XÂY DỰNG MÔ HÌNH CUỐI CÙNG
model_final <- glm(default_payment_next_month ~ ., data = train_set_with_dummies, family = binomial(link = "logit"), na.action = na.omit)
# 3. DỰ BÁO TRÊN CẢ 2 TẬP
pred_prob_train <- predict(model_final, newdata = train_set_final, type = "response")
pred_class_train <- factor(ifelse(pred_prob_train > 0.5, 1, 0), levels = c(0, 1))
pred_prob_test <- predict(model_final, newdata = test_set_final, type = "response")
pred_class_test <- factor(ifelse(pred_prob_test > 0.5, 1, 0), levels = c(0, 1))
# 4. TÍNH TOÁN TẤT CẢ CÁC CHỈ SỐ
# Cho Tập Kiểm tra (Test Set)
conf_matrix_test <- table(Thuc_te = test_set_final$default_payment_next_month, Du_doan = pred_class_test)
# Thêm kiểm tra kích thước của ma trận nhầm lẫn trong trường hợp mất cân bằng cực đoan
if (nrow(conf_matrix_test) < 2 || ncol(conf_matrix_test) < 2) {
warning("Ma trận nhầm lẫn cho tập kiểm tra không phải 2x2. Kiểm tra sự mất cân bằng lớp cực đoan trong dự đoán.")
TN_test <- 0; FP_test <- 0; FN_test <- 0; TP_test <- 0 # Khởi tạo để tránh lỗi
# Cố gắng gán giá trị
if ("0" %in% rownames(conf_matrix_test) && "0" %in% colnames(conf_matrix_test)) TN_test <- conf_matrix_test["0", "0"]
if ("0" %in% rownames(conf_matrix_test) && "1" %in% colnames(conf_matrix_test)) FP_test <- conf_matrix_test["0", "1"]
if ("1" %in% rownames(conf_matrix_test) && "0" %in% colnames(conf_matrix_test)) FN_test <- conf_matrix_test["1", "0"]
if ("1" %in% rownames(conf_matrix_test) && "1" %in% colnames(conf_matrix_test)) TP_test <- conf_matrix_test["1", "1"]
} else {
TN_test <- conf_matrix_test[1, 1]; FP_test <- conf_matrix_test[1, 2]
FN_test <- conf_matrix_test[2, 1]; TP_test <- conf_matrix_test[2, 2]
}
accuracy_test <- (TP_test + TN_test) / sum(conf_matrix_test)
precision_test <- TP_test / (TP_test + FP_test) # Xử lý trường hợp chia cho 0 tiềm ẩn
if (is.nan(precision_test)) precision_test <- 0
recall_test <- TP_test / (TP_test + FN_test) # Xử lý trường hợp chia cho 0 tiềm ẩn
if (is.nan(recall_test)) recall_test <- 0
f1_score_test <- 2 * (precision_test * recall_test) / (precision_test + recall_test)
if (is.nan(f1_score_test)) f1_score_test <- 0
roc_test <- roc(test_set_final$default_payment_next_month, pred_prob_test, quiet = TRUE)
auc_test <- auc(roc_test)
# Cho Tập Huấn luyện (Train Set)
conf_matrix_train <- table(Thuc_te = train_set_final$default_payment_next_month, Du_doan = pred_class_train)
# Thêm kiểm tra kích thước của ma trận nhầm lẫn
if (nrow(conf_matrix_train) < 2 || ncol(conf_matrix_train) < 2) {
warning("Ma trận nhầm lẫn cho tập huấn luyện không phải 2x2. Kiểm tra sự mất cân bằng lớp cực đoan trong dự đoán.")
TN_train <- 0; FP_train <- 0; FN_train <- 0; TP_train <- 0 # Khởi tạo để tránh lỗi
# Cố gắng gán giá trị nếu có thể
if ("0" %in% rownames(conf_matrix_train) && "0" %in% colnames(conf_matrix_train)) TN_train <- conf_matrix_train["0", "0"]
if ("0" %in% rownames(conf_matrix_train) && "1" %in% colnames(conf_matrix_train)) FP_train <- conf_matrix_train["0", "1"]
if ("1" %in% rownames(conf_matrix_train) && "0" %in% colnames(conf_matrix_train)) FN_train <- conf_matrix_train["1", "0"]
if ("1" %in% rownames(conf_matrix_train) && "1" %in% colnames(conf_matrix_train)) TP_train <- conf_matrix_train["1", "1"]
} else {
TN_train <- conf_matrix_train[1, 1]; FP_train <- conf_matrix_train[1, 2]
FN_train <- conf_matrix_train[2, 1]; TP_train <- conf_matrix_train[2, 2]
}
accuracy_train <- (TP_train + TN_train) / sum(conf_matrix_train)
precision_train <- TP_train / (TP_train + FP_train)
if (is.nan(precision_train)) precision_train <- 0
recall_train <- TP_train / (TP_train + FN_train)
if (is.nan(recall_train)) recall_train <- 0
f1_score_train <- 2 * (precision_train * recall_train) / (precision_train + recall_train)
if (is.nan(f1_score_train)) f1_score_train <- 0
roc_train <- roc(train_set_final$default_payment_next_month, pred_prob_train, quiet = TRUE)
auc_train <- auc(roc_train)
# TẠO BẢNG DỰ BÁO MẪU
library(flextable)
library(scales)
# 1. CHUẨN BỊ BẢNG KẾT QUẢ MẪU
prediction_sample_df <- data.frame(
`Khách hàng ID (Mẫu)` = 1:5,
`Xác suất Vỡ nợ Dự báo` = percent(pred_prob_test[1:5], accuracy = 0.1),
`Dự báo Phân loại (Ngưỡng 50%)` = as.character(pred_class_test[1:5]),
`Tình trạng Vỡ nợ Thực tế` = as.character(test_set_final$default_payment_next_month[1:5]), # Sửa từ test_set_collapsed thành test_set_final
check.names = FALSE
)
# 2. TRÌNH BÀY BẢNG
flextable(prediction_sample_df) %>%
set_caption("Bảng 4.20: Ví dụ về kết quả dự báo trên 5 khách hàng mẫu trong tập kiểm tra.") %>%
align(j = 2:4, align = "center", part = "all") %>% # Căn giữa các cột
autofit()
# BẢNG SO SÁNH HIỆU SUẤT
library(flextable)
# 1. TẠO BẢNG SO SÁNH
performance_df <- data.frame(
`Chỉ số` = c("Độ chính xác (Accuracy)", "Độ chuẩn (Precision)", "Độ nhạy (Recall)", "F1-Score", "AUC"),
`Tập Huấn luyện (Train)` = c(accuracy_train, precision_train, recall_train, f1_score_train, auc_train),
`Tập Kiểm tra (Test)` = c(accuracy_test, precision_test, recall_test, f1_score_test, auc_test),
check.names = FALSE
)
# 2. TRÌNH BÀNG BẢNG
flextable(performance_df) %>%
set_caption("Bảng 4.21: So sánh các chỉ số hiệu suất của mô hình.") %>% # Adjusted caption
colformat_double(j = 2:3, digits = 3) %>%
autofit()
# BIỂU ĐỒ SO SÁNH ROC
library(ggplot2)
library(pROC)
# Vẽ 2 đường cong ROC trên cùng một biểu đồ
ggroc(list(`Tập Huấn luyện (Train)` = roc_train, `Tập Kiểm tra (Test)` = roc_test), size = 1) +
geom_segment(aes(x = 1, xend = 0, y = 0, yend = 1), color="grey", linetype="dashed") +
labs(
title = "So sánh Đường cong ROC của Mô hình",
subtitle = paste0("AUC Train = ", round(auc_train, 3), " | AUC Test = ", round(auc_test, 3)),
x = "Tỷ lệ Dương tính giả (1 - Specificity)",
y = "Tỷ lệ Dương tính thật (Sensitivity/Recall)",
color = "Tập dữ liệu"
) +
theme_minimal(base_size = 12) +
theme(legend.position = "bottom")