이전까지는 age, weight, oxygen, runtime, runpulse, rstpulse 데이터를 통해서 maxpulse를 예측하는 예제를 살펴봤습니다. maxpulse는 연속된 값을 가지고 있는 수치-연속형 데이터입니다.
dataset = pd.read_csv('./fitness.csv') dataset.head()
![](http://cedartrees.co.kr/wp-content/uploads/2020/12/스크린샷-2020-12-02-오후-12.13.37.png)
데이터의 특징은 아래와 같습니다.
dataset.info()
RangeIndex: 31 entries, 0 to 30
Data columns (total 7 columns):
# Column Non-Null Count Dtype
— —— ————– —–
0 age 31 non-null int64
1 weight 31 non-null float64
2 oxygen 31 non-null float64
3 runtime 31 non-null float64
4 runpulse 31 non-null int64
5 rstpulse 31 non-null int64
6 maxpulse 31 non-null int64
dtypes: float64(3), int64(4)
memory usage: 1.8 KB
앞으로 하려고 하는 부분은 weight, oxygen, runtime, runpulse, rstpulse, maxpulse 칼럼 정보를 통해서 이 사람이 어느 나이대인가를 예측하는 분류의 문제를 해결해보도록 하겠습니다.
그러나 아쉽게도 예제 데이터는 범주형 컬럼은 없고 모두 수치형-연속형 데이터들입니다. 그렇기 때문에 범주형-순서형 데이터 컬럼을 하나 만들어줘야합니다. 아래와 같은 범주형 데이터 컬럼을 하나 만들겠습니다.
나이가 40대 이하이면 1, 40~50 사이에 있으면 2, 50~60 사이에 있으면 3 이렇게 넣어보겠습니다.
범주형 : 몇개의 범주로 나눠진 자료로 명목형, 순서형 데이터가 있음
* 명목형 : 성별, 성공여부, 혈액형 등 단순히 분류된 자료
* 순서형 : 개개의 값들이 이산적이며 그들 사이에 순서 관계가 존재하는 자료
수치형 : 이산형과 연속형으로 이뤄진 자료로 이산형과 연속적인 형태의 자료가 있음
* 이산형 : 이산적인 값을 갖는 데이터로 출산 횟수 등을 의미
* 연속형 : 연속적인 값을 갖는 데이터로 키나 몸무게 등을 의미
dataset.loc[ dataset['age'] < 40, 'ACODE']= 1 dataset.loc[ (dataset['age'] >= 40) & (dataset['age'] <50), 'ACODE']= 2 dataset.loc[ (dataset['age'] >= 50) & (dataset['age'] <60), 'ACODE']= 3
훈련에 사용하는 컬럼은 나이를 제외한 나머지 컬럼들입니다. 어떤 내용들이 있는지 살펴보면 아래와 같습니다.
![](http://cedartrees.co.kr/wp-content/uploads/2020/12/스크린샷-2020-12-05-오후-2.30.02.png)
해당 데이터를 3차원 평면에 나타내보면 아래와 같습니다. 그래프를 보면 3개의 포인터가 다른 색으로 분류되어 있습니다. 데이터가 많지 않고 5차원 데이터를 3차원으로 축소한 형태이기 때문에 각 분류가 정확하지 않은것 같습니다. 학습 데이터가 좋은 형태로 되어 있다면 아마도 그래프의 각 요소들이 잘 구분되어 있을테지만 아쉽게도 예제 데이터는 그렇지 않은듯합니다.
from mpl_toolkits.mplot3d import Axes3D fig = plt.figure(1, figsize=(8, 6)) ax = Axes3D(fig, elev=-150, azim=110) X_reduced = PCA(n_components=3).fit_transform(dataset[dataset.columns[:-1]]) ax.scatter(X_reduced[:, 0], X_reduced[:, 1], X_reduced[:, 2], c=y, cmap=plt.cm.Set1, edgecolor='k', s=40) ax.set_title("First three PCA directions") ax.set_xlabel("1st eigenvector") ax.w_xaxis.set_ticklabels([]) ax.set_ylabel("2nd eigenvector") ax.w_yaxis.set_ticklabels([]) ax.set_zlabel("3rd eigenvector") ax.w_zaxis.set_ticklabels([]) plt.show()
![](http://cedartrees.co.kr/wp-content/uploads/2020/12/download-4.png)
이제 sklearn 패키지의 분류문제를 풀수 있는 LogisticRegression를 사용해보겠습니다. 사용하는 방법은 LinearRegression과 같이 간단하게 사용할 수 있습니다. x 데이터와 y 데이터는 위에서 설명해드린 데이터를 사용합니다.
그런다음 LogisticRegression에서 옵션을 선택하고 해당 모델을 학습합니다. sklearn은 효율적인 학습을 위해 몇가지 효율적인 학습 알고리즘을 제시합니다. 특히 feature의 수, 학습 데이터의 양, 분류할 문제의 수 등을 따라서 필요한 알고리즘을 선택합니다.
이번 예제는 3개의 분류 문제(multiclass problems)를 풀어야 하기 때문에 ‘newton-cg’ 알고리즘을 사용하도록 하겠습니다. 이 외에도 여러 알고리즘과 파라메터가 있습니다. sklearn 공식 사이트에서 해당 내용들을 확이해보시기 바랍니다.
![](http://cedartrees.co.kr/wp-content/uploads/2020/12/스크린샷-2020-12-05-오후-3.56.59-1024x315.png)
x = dataset[dataset.columns[1:-1]].values y = dataset['ACODE'].values from sklearn.linear_model import LogisticRegression clf = LogisticRegression(solver='newton-cg', max_iter=100).fit(x, y) predict = clf.predict(x) accuracy=(predict.reshape(-1,1) == y.reshape(-1,1)).sum()/len(y) print(accuracy) # 0.8387096774193549 정확도
알고리즘을 통해 확인해보니 0.8387 의 정확도를 보여줍니다. 학습용 데이터가 작기 때문에 테스트용 데이터를 만들 수 없었던 이유로 정확도 계산을 한다고 하기도 좀 애매하지만 더 많은 데이터를 통해서 훈련과 테스트를 해보시길 권해드립니다.
그리고 학습이 완료된 후에 기울기와 절편 정보를 출력해보면 아래와 같습니다.
print('W:{}, b:{}'.format(clf.coef_.T, clf.intercept_.T)) W:[[ 0.46533128 -0.20477993 -0.26055162] [ 0.60397447 -0.08600717 -0.5179662 ] [-0.13946355 0.42710757 -0.28764394] [ 0.21778426 -0.00474545 -0.2130358 ] [ 0.00648806 0.03361824 -0.04010692] [ 0.05094977 -0.07150677 0.02055985]], b:[-116.45602409 30.69276337 85.76326072]
그리고 이러한 데이터를 통해서 직접 행렬곱을 해봐도 같은 결과가 나오는 것을 확인할 수 있습니다.
y_hat = np.matmul(x,clf.coef_.T)+clf.intercept_ y_hat.argmax(axis=1)+1