내일배움캠프/TIL

[TIL]250124_머신러닝 발제

dydatablog 2025. 1. 24. 21:28
  • 주제 : [분류] 은행 고객 이탈여부 분류
  • 사용 데이터 : https://www.kaggle.com/datasets/shubhammeshram579/bank-customer-churn-prediction/data
  • 프로젝트 목표 : 고객 데이터를 분석하여 이탈 유저를 예측하는 분류 모델을 개발하고, 이를 통해 고객 유형별 리텐션 향상 전략을 수립한다.
  • 프로젝트 핵심내용 : 다양한 머신러닝 모델을 활용하여 성과 지표를 분석해 최적의 모델을 선정하고, 고객을 클러스터링한 후 이탈이 예측되는 그룹별 이탈 방지 전략을 제시한다.

PPT 필수 내용 : 1. 모델 별 성과 표 2. 고객 클러스터링 => 구체적인 전략 제시

  • 데이터 준비
    • 데이터 탐색: 각 변수별 분포, 클래스별 분포 차이, 결측치나 이상치 확인
    • 결측값 처리: 평균, 중앙값 대체 혹은 결측치가 아닌 값들을 기반으로 회귀예측을 통한 보완(규모가 작으면 아예 제거도 가능)
    • 이상치 처리: IQR, Z-score 등으로 탐색해 처리

컬럼 확인

# 1. 결측치 확인
df.isnull().sum()
'''
CustomerId         0
CreditScore        0
Geography          1
Gender             0
Age                1
Tenure             0
Balance            0
NumOfProducts      0
HasCrCard          1
IsActiveMember     1
EstimatedSalary    0
Exited             0
dtype: int64
'''

missing_data = df[df.isnull().any(axis=1)]
missing_data
# Geography : CustomerId 15592531
# age : CustomerId 15592389
# HasCrCard : CustomerId 15737888
# IsActiveMember : CustomerId 15792365

# 1-1. 중복값 확인 
duplicates = df['CustomerId'].value_counts()[lambda x: x > 1]
duplicates
"""
15628319    2
15682355    2
"""

# 2. 범주형 컬럼 확인
df.describe(include="object")
"""
	    Surname	Geography	Gender
count	 10002	  10001	  10002
unique	2932	    3	      2
top	   Smith	  France	 Male
freq	  32	     5014	   5458
"""

IQR기법으로 연속형데이터를 가진 컬럼의 이상치 확인

-> 아래와 같은 코드로 Age, Balance, EstimatedSalary, CreditScore 컬럼의 이상치 확인.

# iqr 기법
# age컬럼 안에 결측치 존재하기 때문에 dropna()추가
age_q1 = np.percentile(df['Age'].dropna(), 25)
age_q3 = np.percentile(df['Age'].dropna(), 75)
age_iqr = age_q3 - age_q1
age_lower_bound = age_q1 - 1.5 * age_iqr
age_upper_bound = age_q3 + 1.5 * age_iqr

print(age_upper_bound)
print(age_lower_bound)
''' 
62.0
14.0
'''

# 이상치 확인
age_score_outliers = df[(df['Age'] < age_lower_bound) | (df['Age'] > age_upper_bound)]
print('Age 이상치 개수:', len(age_score_outliers))
print('Lower Bound: ',age_lower_bound,'\nUpper Bound: ', age_upper_bound)
print(age_score_outliers)

'''
      RowNumber  CustomerId      Surname  CreditScore Geography  Gender   Age  \
58           59    15623944        T'ien          511     Spain  Female  66.0   
85           86    15805254      Ndukaku          652     Spain  Female  75.0   
104         105    15804919     Dunbabin          670     Spain  Female  65.0   
158         159    15589975      Maclean          646    France  Female  73.0   
181         182    15789669         Hsia          510    France    Male  65.0   
...         ...         ...          ...          ...       ...     ...   ...   
9753       9754    15705174    Chiedozie          656   Germany    Male  68.0   
9765       9766    15777067       Thomas          445    France    Male  64.0   
9832       9833    15814690  Chukwujekwu          595   Germany  Female  64.0   
9894       9895    15704795        Vagin          521    France  Female  77.0   
9936       9937    15653037        Parks          609    France    Male  77.0   

      Tenure    Balance  NumOfProducts  HasCrCard  IsActiveMember  \
58         4       0.00              1        1.0             0.0   
85        10       0.00              2        1.0             1.0   
104        1       0.00              1        1.0             1.0   
158        6   97259.25              1        0.0             1.0   
181        2       0.00              2        1.0             1.0   
...      ...        ...            ...        ...             ...   
9753       7  153545.11              1        1.0             1.0   
9765       2  136770.67              1        0.0             1.0   
9832       2  105736.32              1        1.0             1.0   
9894       6       0.00              2        1.0             1.0   
9936       1       0.00              1        0.0             1.0   

      EstimatedSalary  Exited  
58            1643.11       1  
85          114675.75       0  
104         177655.68       1  
158         104719.66       0  
181          48071.61       0  
...               ...     ...  
9753        186574.68       0  
9765         43678.06       0  
9832         89935.73       1  
9894         49054.10       0  
9936         18708.76       0  

age_score_outliers.describe() 시행시 max값이 92.
특별히 제거해야할만한 이상치는 보이지 않는것 같다...

'''

결과 : 모든 컬럼값에서 특별히 제거해야할만한 값을 찾지 못했다.

-> 일단 customerID의 중복값 2행과 null값 4행을 제거한 데이터로 EDA진행.


 

- 이탈자 기준 확인하기

# 이탈 고객의 기준 찾기
# 1-1 은행에 잔액 없는 고객 : 500명
df2[(df2['Exited']==1) & (df2['Balance'] == 0)]
# 1-2 은행에 잔액이 남아있는 고객 : 1537명 -> 처리 중?
df2[(df2['Exited']==1) & (df2['Balance'] > 0)]

# 2-1 활동성이 없는 고객 : 1302명
df2[(df2['Exited']==1) & (df2['IsActiveMember'] == 0)]
# 2-2 활동중인 고객 : 735명 -> 처리 중?
df2[(df2['Exited']==1) & (df2['IsActiveMember'] == 1)]

# 3-1 신용카드가 없는 고객 : 613명
df2[(df2['Exited']==1) & (df2['HasCrCard'] == 0)]
# 3-2 신용카드가 있는 고객 : 1424명 -> 처리 중?
df2[(df2['Exited']==1) & (df2['HasCrCard'] == 1)]

# 4-1 가입된 상품이 없는 고객 : 0명
df2[(df2['Exited']==1) & (df2['NumOfProducts'] == 0)]
# 4-2 가입된 상품이 있는 고객 : 2037명 -> 처리 중?
df2[(df2['Exited']==1) & (df2['NumOfProducts'] > 0)]

파이썬 300제 31~40

문자열 대문자 / 소문자로 바꾸기 : .upper(), .lower(), .capitalize(), .title()

ticker = "btc_krw"
ticker.upper() #모든 문자를 대문자로
# 출력: BTC_KRW

ticker = "BTC_KRW"
ticker.lower() #모든 문자를 소문자로
# 출력: btc_krw

n = 'hello'
n.capitalize() #맨 앞글자만 대문자로
# 출력: Hello world

n = 'hello world'
n.title() #알파벳 외의 문자(숫자, 특수기호, 띄어쓰기 등)로 나누어져 있는 영단어의 첫 글자를 모두 대문자로
# 출력: Hello World

 

문자열 공백 제거 : .rstrip()

data = "039490     "
data.rstrip()