데이터 안에서 게의 나이를 예측 하는 kaggle 의 playground 에 참여해보았다.
https://www.kaggle.com/competitions/playground-series-s3e16
총 8개의 독립변수[피처]를 토대로 종속변수인 게의 나이를 예측하는 문제다.
문제의 평가 기준은 MAE(Mean Absolute Error) 로 예측한 값을 추축한다.
Error 를 측정하는 것이기 때문에 0에 가까울 수록 높은 예측력을 갖고 있게 된다.
변수는 다음과 같다. (Age 를 제외한 8개는 모두 독립변수)
Sex | object | 게의 성 (Male, Female, Intermediate) |
Length | float | 게의 길이(feet 기준) |
Diameter | float | 게의 지름(feet 기준) |
Height | float | 게의 높이(feet 기준) |
Weight | float | 게의 무게(ounces 기준) |
Shucked Weight | float | 껍질 없는 무게(ounces 기준) |
Viscera Weight | float | 장기 무게(ounces 기준) |
Shell Weight | float | 껍질의 무게(ounces 기준) |
Age | int | 게의 나이(달 기준) |
MAE 이기 때문에 선형회귀로 베이스 라인을 잡아보고 빠르게 진행해보겠다.
path='/kaggle/input/playground-series-s3e16/'
train_df = pd.read_csv(path+'train.csv')
test_df = pd.read_csv(path+'test.csv')
sample_sub = pd.read_csv(path+'sample_submission.csv')
print(train_df.shape, test_df.shape)
(74051, 10) (49368, 9)
train_df 변수가 9개가 아닌 10개가 나왔고, test_df 는 8개가 아닌 9개가 나왔다. test_df 에는 예측하고자 하는 Age 가 없을 것이기에 train_df의 변수 - 1 이기 때문에 10 과 9가 나온 것이다.
train_df.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 74051 entries, 0 to 74050
Data columns (total 10 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 id 74051 non-null int64
1 Sex 74051 non-null object
2 Length 74051 non-null float64
3 Diameter 74051 non-null float64
4 Height 74051 non-null float64
5 Weight 74051 non-null float64
6 Shucked Weight 74051 non-null float64
7 Viscera Weight 74051 non-null float64
8 Shell Weight 74051 non-null float64
9 Age 74051 non-null int64
dtypes: float64(7), int64(2), object(1)
memory usage: 5.6+ MB
id 값은 제거해도 독립변수와 연관이 없기에 제거하면 되고 제거 후엔 독립변수가 총 8개가 된다.
앞서 말했던 것 처럼 train_df, test_df 에 각각 id 를 제거하면 변수는 10 - 1 = 9(Age 포함), 9 - 1= 8 이 된다.
각 독립 변수의 고유한 값의 갯수가 몇개 있는지를 아는 것이 EDA 과정에서 중요한데 연속형 숫자를 가질 것으로 예상되는 변수들이 (무게, 길이)라 의미는 없을 것이고, Sex 정도만 고유한 값이 몇개 인지 확인해보자.
train_df['Sex'].unique()
array(['I', 'M', 'F'], dtype=object)
독립변수에 대해서 알아봤을 때 나왔던 M=Male, F=Female, I = Intermediate 가 나온다.
게에 대한 성별 관련 도메인을 공부해보았는데 Intermediate(중간의) 라고 할만큼 게의 성별이 애매한 경우가 없는 것 같더라.(Sexual dimorphism)
https://en.wikipedia.org/wiki/Crab
그냥 다른 말로 성별을 구별하지 못하고 데이터가 기록되었다 정도로 이해하면 될 것 같다.
object 형태로 저장되어 있기에 Sex 는 원 핫 인코딩으로 처리를 해본 후 가장 간단한 lineargression 으로 베이스 라인을 선택해보겠다.
all_data = pd.concat([train_df,test_df],ignore_index=True)
all_data = all_data.drop(columns='id')
all_data_encoding = pd.get_dummies(all_data)
print(all_data_drop.info())
print(all_data_drop.head())
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 123419 entries, 0 to 123418
Data columns (total 11 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 Length 123419 non-null float64
1 Diameter 123419 non-null float64
2 Height 123419 non-null float64
3 Weight 123419 non-null float64
4 Shucked Weight 123419 non-null float64
5 Viscera Weight 123419 non-null float64
6 Shell Weight 123419 non-null float64
7 Age 74051 non-null float64
8 Sex_F 123419 non-null uint8
9 Sex_I 123419 non-null uint8
10 Sex_M 123419 non-null uint8
dtypes: float64(8), uint8(3)
memory usage: 7.9 MB
None
Length Diameter Height Weight Shucked Weight Viscera Weight \
0 1.5250 1.1750 0.3750 28.973189 12.728926 6.647958
1 1.1000 0.8250 0.2750 10.418441 4.521745 2.324659
2 1.3875 1.1125 0.3750 24.777463 11.339800 5.556502
3 1.7000 1.4125 0.5000 50.660556 20.354941 10.991839
4 1.2500 1.0125 0.3375 23.289114 11.977664 4.507570
Shell Weight Age Sex_F Sex_I Sex_M
0 8.348928 9.0 0 1 0
1 3.401940 8.0 0 1 0
2 6.662133 9.0 0 0 1
3 14.996885 11.0 1 0 0
4 5.953395 8.0 0 1 0
결측치가 없고, Sex 가 원 핫 인코딩으로 잘 저장된 것도 확인된다.
all_data_encoding.drop(columns='Age',inplace=True)
X = all_data_encoding[:len(train_df)]
Y = train_df['Age']
from sklearn.model_selection import train_test_split
x_train,x_test,y_train,y_test = train_test_split(X,Y,random_state=100,shuffle=True,test_size=0.2)
from sklearn.linear_model import LinearRegression
model_LR = LinearRegression()
model_LR.fit(x_train,y_train)
y_pred = model_LR.predict(x_test)
from sklearn.metrics import mean_absolute_error
print(f'{y_pred[:5]}\n{y_pred.astype(int)[:5]}')
print(f'{mean_absolute_error(y_test,y_pred)} \n{mean_absolute_error(y_test,y_pred.astype(int))}')
[10.30036098 10.23518101 6.83617007 7.23905981 10.2260716 ]
[10 10 6 7 10]
1.4867050765343677
1.4421038417392478
Age 가 소수일 필요는 없으니 MAE 오차도 소수일때와 정수로 변경했을 때 차이가 나고, 정수일때 오류를 더 줄일 수 있었다.
test_df_encoding = all_data_encoding[len(train_df):]
y_pred_test = model_LR.predict(test_df_encoding)
print(y_pred_test.astype(int)[:5])
[ 7 7 10 9 7]
test_df['Age'] = y_pred_test.astype(int)
test_df_sub = test_df[['id','Age']]
test_df_sub.set_index('id',inplace=True)
print(test_df_sub.head())
test_df_sub.to_csv('submission.csv')
이대로 캐글에 제출해보았다.
원 핫 인코딩으로 Sex 를 처리만 하고 베이스라인 모델로 LinearRegression 모델의 결과로서 MAE 1.44 오류로 현재 점수가 나왔다.
대회의 리더보드에 현재 571 중 447 등을 했다. 대충 78% 정도 수준에 머문다.
일단 EDA 과정을 건성으로 했으니, EDA 와 feature engeering 을 통해서 MAE 수치를 줄이도록 해봐야 겠다.
'IT > Data 분석' 카테고리의 다른 글
[게 나이 예측] EDA - 1 (0) | 2023.06.05 |
---|---|
[차원 이동] 베이스라인 모델 - 1 (0) | 2023.05.25 |
[차원 이동] 분석 12회차[독립변수 파악3] (0) | 2023.05.13 |
[차원 이동] 분석 11회차[독립변수 파악2] (0) | 2023.04.27 |
[차원 이동] 분석 10 회차[독립변수 파악] (0) | 2023.04.27 |