오늘 목표는 대본을 최대한 빨리 짜서 다른 학습을 진행해 보려했으나 대본짜는게 괴장히 늦어지고 수정을 진행하면서 시간을 너무 많이 사용해서 학습을 많이 진행하지 못했다.
오늘 학습내용 소개 순서는
1. 과제를 마무리하며 알게 된 내용
2. 기초 수학 특강
3. 회고
순서로 진행하겟습니다.
☑️과제 발표 준비
지금까지 과제를 준비하며 많은 부분을 학습하게 되었다고 생각했지만
좁은 학습분량인 과제 분량에도 아직 모르는 것들이 존재했고 머신러닝 학습에 대한 평가를 하는게 새롭게 느껴졋다.
1. 최빈값 mode를 사용할때[0]의 역할
- fillna(df.mode()[0])에서 [0]의 역할은 최빈값의 가장 첫 번째 값을 최빈값으로 설정하겟다고 설정하는 것이다.
2. Logistic Regrection의 모델 생성시 설정
model = LogisticRegrection(max_iter=100)
- max_iter=100의 의미는 학습을 최대 100번 반복으로 설정하는 코드입니다.
- 최대반복 수를 설정하는 이유는 데이터셋의 크기가 클수록 크게 설정해야하는 것이 맞지만 학습이 오류가 나서 학습을 멈춰버리는 경우가있어서 적절한 값을 설정해주어야 한다.(기본값은 100)
3. RandomForest의 모델 생성시 설정
model = RandomForest(random_state=42)
- random_state를 설정하는 이유는 모델 생성에서 결과를 일관되게 재현 및 비교하기 위해 랜덤 스테이트를 설정하는 것
4. XGBoost의 모델 생성시 설정
model = XGBoost( use_label_encoder=False, eval_metric='logloss')
- use_label_encoder=False룰 설정하게 되면 LabelEncoding을 사용했을 때 나올 수 있는 경고 메세지를 무시해준다.
- eval_metric='logloss'는 로그 손실 값을 계산하고 출력하여 학습상태를 확인 할 수 있다.
5. Classification_report 해석
우선 Classification의 요소로는
예측하는 값들을 개별 클래스로 나누어 준다
precision (정밀도): 진행한 예측이 얼마나 정밀하게 예측이 되었는지 보여 준다.
recall(재현율): 모델을 학습할 때 실제 계산과 테스트 계산이 얼마나 잘 이루어 졌는지 확인한다.
f1-score: 정밀도와 재현율의 균형 조화 점수를 보여준다.
support: 학습을 진행할 때 몇 개의 값들을 사용했는지 보여준다.
Macro avg: 두 클래스의 평균 성능을 동일한 가중치로 평가한 값
Weighted avg: 각 클래스의 샘플 수에 따라 가중치를 적용해 계산된 평균 성능
6. confusion_metrix 해석 방법
[[89, 16],
[16, 58]]
89 = 첫 번째 클래스를 정확하게 예측한 수
16 = 첫 번째 클래스를 두 번째 클래스로 잘못 예측한 수
16 = 두번째 클래스를 첫 번째 클래스로 잘못 예측한 수
58 = 두번째 클래스를 정확히 예측한 수
결론: 첫번째 클래스에 대한 예측은 성능이 좋고 두 번째 클래스 예측 또한 좋지만 첫 번째 클래스 예측이 더 성능이 좋다.
☑️기초 선형 대수학(행렬과 연산)
스칼라(온도, 길이, 질량)
- 크기만있고 방향은 없다.
- 물리적 단위를 포함 할 수 있음
- 일반적으로 실수로 표현
벡터(힘, 속도, 위치)
- 벡터는 크기와 방향으로 데이터를 표현
- 벡터의 표현: 열의 형태로 나타냄
- v1, v2는 벡터의 성분이며 각 차원별 크기
벡터의 연산
- 벡터의 덧셈과 뺄셈: 같은 서분끼리 더하거나 뺌 a +b = (a1 + b1, a2 + b2....)
- 스칼라 곱: 벡터와 숫자의 곱으로 벡터 성분에 숫자를 곱함 k*a = (k*a1, k*a2...)
- 벡터의 크기: 벡터의 길이를 나타내는 스칼라 값 a = (a1제곱,a2제곱,...an제곱)
- 벡터의 내적: 주 벡터 사이의 관계를 나타내는 연산으로, 두 벡터를 곱해서 하나의 숫자(스칼라)를 구하는 방법
- 코사인 유사도: 두 벡터가 이루는 각도의 코사인 값을 이용해 벡터 간의 유사성을 특정하는 방법(값이 1에 가까울수록 두 벡터는 동일한 방향, 값이 0이면 두 벡터는 서로 수직, 값이 -1에 가까울수록 두 벡터는 반대 방향)
Word Embedding: 충분히 잘 학습되었다면 단어에 대한 연산이 가능
코사인 유사도 활용
-문서 유사도 측정: 텍스트 데이터에서 단어의 빈도를 벡터로 표현하고, 문서간의 유사성을 측정
-이미지 검색: 이미지의 특징 벡터를 비교하여 이미지를 찾거나 분류할 때 사용
-추천 시스템: 사용자와 아이템의 특징을 벡터로 나타내어, 유사한 사용자나 아이템을 찾아 비슷한 특징을 가진 사람들 끼리 매칭 혹은 아이템 추천
행렬(벡터에서 차원을 늘린 것)
숫자나 변수들을 직사각형 형태로 배열한 것, 행과 열로 구성 됨
- 행렬의 덧셈과 뺄셈: 같은 위치의 요소끼리 더하거나 뺌(두 행렬의 크기가 같아야한다.)
- 행렬의 스칼라 곱: 행렬의 모든 요소에 스칼라 값을 곱한 결과
- 전치 행렬: 행과 열을 바꾼 행렬
- 행렬의 곱셈: 원소 계산(각 행의 원소와 열의 원소를 곱한 후 더함), 행렬 곱의 조건(A가 m*n 행렬이고 B가 n*p행렬일 때, A의 열수와 B의 행수가 같아야하고, 이경우 곱셈AB는 m*p행렬을 만듦)(행렬곱셈도 내적으로 이루어져이싸고 이해하면 편하나)
특수행렬
- 단위행렬: 대각선의 원소가 1이고 나머지가 모두 0인 정방행렬 A*I = A, I*A = A
- 영행렬: 모든 원소가 0인 행렬 A + 0 = A
- 대각행렬: 주대각선에만 원소가 존재하고, 나머지 원소는 모두 0인 행렬(행렬 곱 연산이 비교적 단순하며, 대각선 원소끼리만 연산에 영향을 줌)
행렬의 활용
- 데이터 분석: 평균, 표준펴차 등 통계저 수치를 구할 때 각 열의 값을 기반으로 연산을 수행, 행렬의 곱셈을 사용해 데이터를 변환하거나, 피처(변수)들의 상관관계를 계산하여 데이터의 패턴을 분석, 주성분 분석(PCA) 같은 방법을 통해 다차원 데이터를 저차원으로 축소할 때도 행렬 연산이 활용됨
- 이미지 처리: 픽셀 값으로 이루어진 2차원 행렬로 표현됨
- 딥러닝에서 뉴런의 활성화 값을 결정(행렬 연산은 입력 데이터와 가중치를 처리하는 기본적인 방법)
☑️ 회고
오늘 발표 준비를 완료하였고 제출 기간 전까지 발표자료의 완성도를 높이는 시간과 도전과제에 대한 내용을 정리해야할 듯하다.
학습을 따로 진행하지 못해 조금 아쉬운 날이였지만 밀리진 않았지만 밀린듯한 느낌을 주던 필수과제를 마무리해서 속은 시원하다.
선형 대수학은 처음 들어보는 단어들이 매우 많아서 이해는 못하였지만 아 저런 수학 공식들을 사용해서 딥러닝모델이 학습을 진행하는구나 아직은 먼 이야기같아 보이니 딥러닝 코드들이 어떤 기능을 가지는지에 대해서 학습하고 수학에 대한 공부를 진행해야겟다.
이제는 이해되는 것보다 저게 뭐지 저런 것이 있구나하는 내용들이 많아서 감이 안잡히기 시작해 현타가 살짝 오지만 전문가는 아니더라도 코드를 보고 이해하고 잘못된 부분을 보면 어떻게 왜 잘못된 것인지 알 수 있을 때까지 노력하고싶다.
mean_value = df['PurchaseAmount'].mean() df['PurchaseAmount']= df['PurchaseAmount'].apply(lambda x: mean_value if x < lower_bound or x > upper_bound else x)
스케일이 다른 피처가 있는 경우: 예를 들어, 한 피처는 수백 단위의 값을, 다른 피처는 소수점을 가진 값을 가질 때 정규화가 필요합니다.
거리 기반 알고리즘: k-NN, SVM, 그리고 신경망은 피처들의 상대적인 크기에 매우 민감합니다.
경사 하강법을 사용하는 경우: 피처들의 값이 크게 차이가 나면 학습 과정이 느려질 수 있습니다.
6. 범주형 데이터 선별 및 인코딩:
ProductCategory와 CustomerGender 열을 인코딩하세요.
df['ProductCategory'] = df['ProductCategory'].map(lambda x: 0 if x == 'Electronics' else 1 if x == 'Clothing' else 2) df['CustomerGender'] = df['CustomerGender'].map(lambda x: 0 if x == 'Female' else 1)
X = df.drop('Survived', axis=1) y = df['Survived']
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
3. 3개 이상의 분류모델을 만들어주세요
from sklearn.linear_model import LogisticRegression from sklearn.tree import DecisionTreeClassifier from sklearn.ensemble import RandomForestClassifier from sklearn.svm import SVC from sklearn.neighbors import KNeighborsClassifier from sklearn.metrics import accuracy_score, precision_score, recall_score, f1_score
import pandas as pd from sklearn.impute import SimpleImputer from sklearn.cluster import KMeans from sklearn.metrics import adjusted_rand_score, homogeneity_score, completeness_score
서열 척도: 순서나 대소 관계가 의미가 있지만 비례관계를 나타내지 않음(설문지 만족도 평가, 성적 등급, 순위)
2) 양적: 거리, 몸무게등 수치로 표현, 연산가능
구간 척도: 대소 관계와 함께 값들간의 차이에 의미가 있는 데이터, 0의 값은 절대적이지 않고 임의로 정한 기준(온도, IQ, 날짜와 시간)
비율 척도: 절대적 0을 포함하며 비율 비교가 가능한 데이터(키, 몸무게, 시험 점수, 거리)(절대온도는 0의값이 정해져있어서 비율척도)
2. 데이터의 연속성
1) 이산형 데이터: 연속적인 값이 아닌 정해진 범위 내의 특정 값으로만 표현
값이 하나하나 개별적으로 구분 되는 변수로 주로 정수 값을 가지며 불연속적임(주사위눈, 시험점수, 학생 수)
2) 연속형 데이터: 연속적인 값을 가지며, 범위 내에서 무한히 많은 값으로 표현
값이 연속적임, 값 사이에 무한히 많은 세부적인 값이 존재(사람의 키, 온도, 시간)
3. 데이터 전처리
1) 질적 데이터(명목척도, 서열척도)는 숫자로 변환하여, 모델에 입력해야함
명목척도: 원 핫 인코딩(숫자에 구분만 짓게하고 숫자 크기 차이에 의미를 두지 않기 위해 한다.)
서열척도: 라벨 인코딩(숫자에 의미를 넣어 대소 관계를 구분 지어야할 때)
2) 양적 데이터(등간, 비율 척도)는 숫자 그대로 사용가능
등간 척도 데이터는 비율 척도처럼 절대적 의미가 없기 때문에 주의
-비율연산을 피해야함(값을 두 배로 하거나, 나누기 연산은 의미가 없음 EX. 섭씨 온도20도의 두 배는 40도라고 인식하지 않도록 해야 함)
-정규화: 0~1사이의 정규화보다 표준화(Standard)가 적절
-피처 엔지니어링: 차이를 강조한 특징을 생성하는 것이 좋음(날짜 데이터를 사용할 때 특정 날짜에서 얼마나 시간이 흘렀는지로 표현)
-분류 모델에 클래스로 사용: 순서나 차이만을 반영하도록 데이터 변환(구간별로 범주화 - 온도를 여러 구간(저,중,고온)으로 나눔
4. 데이터 시각화(이상치를 처리하는 가능성이 큰 데이터를 보여주기도 한다.)
질적 데이터: 카테고리나 범주의 빈도와 비율 시각화(막대 그래프, 파이 차트, 히트맵)
양적 데이터: 데이터의 분포, 관게, 변화 추이를 시각화(히스토그램, 산점도, 선 그래프, 상자그림)
5. 데이터의 중심지표란?
데이터의 중심 경향을 나타내는 값으로 주어진 데이터의 대표적인 값
-평균mean(이상치에 민감)
-중앙값median(이상치에 영향을 덜 받음)
-최빈값mode(이상치에 영향을 덜 받음)
-데이터 분포 형태에 따른 중심 지표 비교
대칭: 데이터가 정규 분포처럼 돠우 대칭으로 나타나는 분포(사람의 키, 시험점수, 제품 품질)
왼쪽꼬리: 데이터가 왼쪽으로 치우쳐있을 때 나타나는 분포(기계고장률, 퇴직 연령)
오른쪽 꼬리: 데이터가 오른쪽으로 치우쳐져 있을 때 나타나는 분포(소득 분포, 주택 가격)
6. 데이터의 중심 지표의 중요성
데이터의 대표성 활용
1) 결측치, 이상치 대체
2) 데이터 표준화:
-데이터의 분포를 평균이 0, 표준편차가 1(standardscaler)
-표준화된 값은 원래 값이 평균으로부터 얼마나 떨어져있는지 나타내는 상대적인 거리
-표준화의 중요성: 데이터가 서로 다른 단위나 범위를 가질 경우, 학습이 왜곡될 수 있음
3) 모델 선택
-평균 중심의 데이터
데이터가 대칭적: 선형 모델(선형 회귀, SVM)
-중앙값 중심의 데이터
데이터가 치우쳐져 있거나 이상치가 많을 때: 비선형 모델(로버스트 회귀, 랜덤 포레스트)
-최빈값 중심의 데이터:데이터가 명목형(카테고리형)인 경우나 이산형 데이터
주어진 데이터의 주변 이웃 중 가장 많이 나타나는 값 예측(K-이웃)
이산형 결과 예측 시(로지스틱 회귀)
범주형 데이터 기반 분류( 나이브 베이즈)
7. 데이터 산포도
데이터가 평균이나 중앙값을 중심으로 얼마나 퍼져 있는지 나타내는 지표
편차variance:각 데이터 값과 데이터의 평균 사이의 차이
분산variance: 편차 제곱의 평균
표준 편차Standard Deviation: 분산의 제곱근으로 단위가 원래 데이터와 같음
사분위수 범위IQR: 중간 50% 데이터의 범위를 나타내는 지표(데이터의 1사분위수(Q1) 3사분위수(Q3)의 차이
8. 데이터 상관 관계(수치로 검색해서 보고 선택하는게 좋다)
-양의 상관관계: 한 변수가 증가할 때 다른 변수도 증가하는 관계
-음의 상관 관계: 한 번수가 증가할 때 다른 변수는 감소하는 관계
-무 상관관계:두변수 간에 일정한 관계가 없음(0에 가까울수록 무상관관계다)
-상관계수: 상관관계의 정도를 수치화한 값이 상관계수(피어슨 상관계수 공식/한계: 주로 선형 관계를 측정하기 때문에 두 변수 간의 관계가 비선형일 경우 이를 제대로 반영하지 못 할 수 있음)
산점도: 상관계수에 따른 데이터 분포 시각화
특징(feature)선택
중복정보제거(상관관계가 높은 변수는 유사한 정보를 담고 있을 가능성이 큼,중복되는 변수들 제거하여 모델의 복잡성을 줄이고 성능을 향상 시킬 수 있다.)
중요한 특징 식별: 종속 변수(출력)과 상관관계가 높은 독립변수(입력)을 선택함으로써 모델의 성능을 향상 시킬 수 있음
9. 확률과 확률 분포
확률: 어떤일이 일어날 가능성을 나타내는 수치
확률 분포: 가능한 경우에 대한 각각의 확률을 나타낸 것
확률의 정의: 특정 사건이 발생하는 경우의 수를 전체 가능 경우의 수로 나눈 값(동전 던지기, 카드 뽑기)
확률의 법칙
어떤 사건 A의 확률은 0에서 1 사이의 값(전체 확률의 합은 1)
확률의 덧셈 법칙: 두 사건 A,B가 있을 때, 둘중 하나가 발생할 확률(두 사건의 확률을 더하고 동시에 일어날 확률을 뺌)
확률의 곱셈 법칙: 두 사건 A,B갈 동시에 일어날 확률(A가 발생활 확률과 A가 발생한 후에 B가 발생할 확률의 곱(서로 독립적일 땐 발생 여부에 영향없음)
여사건 확률: 어떤 사건 A가 일어나지 않을 확률은 1에서 A가 발생할 확률을 뺀 값
조건부 확률: 어떤 사건 a가 발생했을 때, 다른 사건b가 발생할 확률
머신러닝에서의 확률
-다중 클래스 분류:소프트맥스 함수를 통해 각 클래스별 확률을 구함(숫자 이미지 분류)
확률분포: 가능한 모든 사건과 각 사건에 대한 확률을 나타낸것
종류
-이산 확률 분포: 이산형 데이터가 가질 수 있는 각각의 값과 그에 대한 확률(주사위 눈금, 로또 번호 추첨, 머신러닝 분류 모델)
-연속 확률 분포:연속형 데이터가 특정 구간에 속할 확률(하루 온도 20~30도일 확률, 금융시장의 주가 확률)
☑️회고
1주차
배깅이란?
배깅(Bagging)은 여러 모델을 독립적으로 학습시키고 예측을 평균내거나 다수결 투표로 최종 예측을 수행한다.
2주차
언제 정규화를 진행할까?
스케일이 다른 피처가 있는 경우: 예를 들어, 한 피처는 수백 단위의 값을, 다른 피처는 소수점을 가진 값을 가질 때 정규화가 필요합니다.
거리 기반 알고리즘: k-NN, SVM, 그리고 신경망은 피처들의 상대적인 크기에 매우 민감합니다.
경사 하강법을 사용하는 경우: 피처들의 값이 크게 차이가 나면 학습 과정이 느려질 수 있습니다.
StandardScaler 사용할 상황은?
데이터의 분포가 정규분포(가우시안 분포)일 때 많이 사용 수치형 데이터에만 사용 가능
MinMaxScaler란?
값의 범위를 0과 1사이로 조정하여 정규화를 진행해 모델학습에 도움을 준다.
중복값 제거
df = df.drop_duplicates(subset='TransactionID') TransactionID 열에서 같은 값이 여러 번 나타나는 행 중에서 첫 번째 행을 남기고, 그 외의 중복된 행들을 제거하는 역할
IQR을 사용해 제거 및 대체했을 때
제거
df_no_outliers = df[(df['PurchaseAmount'] >= lower_bound) & (df['PurchaseAmount'] <= upper_bound)] 모든 값이 사라짐
대체
mean_value = df['PurchaseAmount'].mean() df['PurchaseAmount'] =df['PurchaseAmount'].apply(lambda x: mean_value if x < lower_bound or x > upper_bound else x) PurchaseAmount 모든값이 같은 값으로 바뀜
print(f"Shape of the dataset {df_sh}") print(f"Columns in the dataset: {df_index}")
df.head()
df.head(-1)
이제 f-string을 사용하는 방법은 버벅이지도 않고 바로 생각할 수 있게 되었다.
☑️ 데이터 전처리
텍스트 데이터에는 불용어(쓸모없는 단어, 구두점 등)가 많습니다. 해당 부분을 없애주는 처리가 필요합니다. 텍스트 데이터에 대한 전처리를 해주세요.
import re
def preprocess_text(text): if isinstance(text, float): return "" text = text.lower() text = re.sub(r'[^\w\s]', '', text) text = re.sub(r'\d+', '', text) text = text.strip() return text
위 코드를 이용하여 content열의 문자를 소문자로, 구두점 제거, 띄어쓰기 제외 빈칸 제거를 시키는 함수를 정의 하였고
content열에만 적용 시켰다.
☑️ feature 분석
데이터를 잘 불러오셨다면 해당 데이터의 feature를 찾아야 합니다. 해당 넷플릭스의 데이터에는 리뷰가 1점부터 5점까지 있습니다. 해당 데이터의 분포를 그래프로 그려주세요.
import seaborn as sns # 시각화 라이브러리 import matplotlib.pyplot as plt # 그래프 표시 라이브러리
# 리뷰 점수 빈도 계산 score_counts = df['score'].value_counts()
# 그래프 만들기 plt.figure(figsize=(10, 7)) # 색상 넣기는 강의 자료에서 찾았습니다. palette = 'viridis' # X축에 점수, Y축에 해당 점수의 개수 sns.barplot(x=score_counts.index, y=score_counts.values, palette='viridis') plt.xlabel('Score') # X축 레이블 plt.ylabel('Count') # Y축 레이블 plt.title('Distribution of Review Scores') # 그래프 제목 plt.show()
위 코드를 작성하여 점수별 분포를 막대 그래프로 표현 하였다.
☑️ 리뷰 예측 모델 학습시키기(LSTM)
이제 어떤 리뷰를 쓰면 점수가 어떻게 나올지에 대해서 예측을 해보고 싶습니다. 로지스틱 회귀 등을 사용하여, 리뷰에 대한 점수 예측을 진행해보세요
import torch import torch.nn as nn import torch.optim as optim from torchtext.data.utils import get_tokenizer from torchtext.vocab import build_vocab_from_iterator from torch.utils.data import DataLoader, Dataset from sklearn.model_selection import train_test_split from sklearn.preprocessing import LabelEncoder
reviews = df['content'].fillna('') # 리뷰가 없는 경우 공백으로 대체 ratings = df['score']
# 토크나이저 및 어휘 집합 생성 tokenizer = get_tokenizer("basic_english")
def yield_tokens(df_iter): for text in df_iter: yield tokenizer(text)
# 텍스트 파이프라인: 텍스트 -> 토큰 -> 인덱스 def text_pipeline(x): return [vocab[token] for token in tokenizer(x)]
# 레이블 파이프라인: 점수(1-5)를 0부터 시작하는 인덱스로 변환 label_encoder = LabelEncoder() train_ratings_encoded = label_encoder.fit_transform(train_ratings) test_ratings_encoded = label_encoder.transform(test_ratings)
class ReviewDataset(df): # 초기화 메서드 def __init__(self, reviews, ratings, text_pipeline, lable_pipeline): # 각 데이터를 변수로 저장 self.reviews = reviews self.ratings = ratings self.text_pipeline = text_pipeline self.label_pipeline = label_pipeline
# 데이터 셋의 크기 반환 def __len__(self): return len(self.reviews)
# 인덱스를 사용해 특정 데이터 항목 가져오기 def __getitem__(self, idx): review = self.text_pipeline(self.reviews[idx]) rating = self.label_pipeline(self.ratings[idx]) # 리뷰와 점수 텐서로 변환 return torch.tensor(review), torch.tensor(rating)
# 데이터 셋 정의 train_dataset = ReviewDataset(train_reviews, train_ratings, text_pipeline, label_pipeline) test_dataset = ReviewDataset(test_reviews, test_ratings, text_pipeline, label_pipeline)
# 데이터 로더 정의 BATCH_SIZE = 64
# LSTM모델 정의 class LSTMModel(nn.Module): def __init__(self, vocab_size, embed_dim, hidden_dim, output_dim): # super()은 부모 클래스의 메서드나 속성을 호출 # nn.Module의 초기화 메서드를 호출해 초기화 수행 super(LSTMModel, self).__init__() # 임베딩을 진행하는 이유: 단어를 고차원 공간에서의 실수 벡터로 변환 # 모델이 텍스트의 의미를 이해하게 만든다. # sparse=True는 희소 인베딩을 활성화 한다. # 임베딩 레이어가 메모리 효율적으로 작동하게 만들며, 단어 인덱스 만을 사용하게 만든다. self.embedding = nn.EmbeddingBag(vocab_size, embed_dim, sparse=True) # LSTM 정의 # 시퀀스 데이터를 처리 역할 # LSTM은 장기 의존성 학습으로 문맥의 정보를 잘 기억 # 텍스트 시퀀스는 시간적으로 의존성을 가지므로 LSTM을 통해 정보를 효과적으로 학습 # batch_first=True는 입력텐서의 첫 번째 차원이 배치 크기로 만든다. self.lstm = nn.LSTM(embed_dim, hidden_dim, batch_first=True) self.fc = nn.Linear(hidden_dim, output_dim)
# 모델의 순전파 정의 # text는 모델에 입력 되는 텍스트 데이터 # 순전파란? 입력 데이터가 모델을 통해 전달되어 최종 출력이 생성 되는 과정 의미 # 출력 레이어에서 예측값이 생성된다. def forward(self, text): embedded = self.embedding(text) # unsqueeze(0)는 입력 텐서에 배치차원을 추가하는 방법 # 왜 추가하는지? LSTM은 일반적으로 (배치 크기, 시퀀스 길이, 특성 수)의 형태를 가진 텐서를 입력받는데 # embedded 텐서가 (시퀀스 길이, 특성 수)의 형태일 경우, unsqueeze(0)을 사용하여 (1, 시퀀스 길이, 특성 수)의 형태로 변환해 LSTM에 맞춘다. output, (hidden, cell) = self.lstm(embedded.unsqueeze(0)) # hidden[-1]은 모든 숨겨진 상태의 텐서에서 마지막에 숨겨진 상태를 의미 return self.fc(hidden[-1])
위 코드는 완성이 된것이 아니다.
작성해나가며 새롭게 알게 된 정보들을 정리하고 적용해나가다가
너무 어렵고 감이 잡히지않아 멈추게 되었다 (공부를 마치는 시간은 이미 지나 버림)
위 코드 설명은 생략하겟다.(지금 머리가 너무 볶잡해서..)
☑️ 회고
오늘 공부하면 만난 정보와 오류나 궁금증들을 공유해보고자 한다.
데이터 셋 불러오기
1. 처음부분 마지막부분 5개씩 가져오기
2가지 방벙이 있다는 것을 확인했다
df.head
------------------------
df.head()
df.head(-1)
이 두가지 방법 중에서 가독성이 두번 째 방법이 더 좋은 것으로 보인다.
데이터 전처리
1. 사용자 지정 함수 (def)를 데이터 프레임에 적용 시키는 방법을 모르겟음 apply와 lambda함수를 사용하여 적용(lambda 함수의 활용법을 더 알아봐야할듯) lambda는 임의의 함수, 맵핑 등에 사용 가능함(지금 알고있는 방식이 2가지)
2. 텍스트의 불필요한 부분만 제거하는 re의 표현식
. : 임의의 한 문자 (줄바꿈 문자는 제외) \w : 알파벳 문자, 숫자, 언더스코어 ([a-zA-Z0-9_]) \W : 문자, 숫자, 언더스코어가 아닌 모든 것 \d : 숫자 ([0-9]) \D : 숫자가 아닌 것 \s : 공백 문자 (스페이스, 탭, 줄바꿈) \S : 공백이 아닌 문자
w랑 s는 묶어서 사용했는데 왜 d+는 따로 사용했는지
* : 0번 이상 반복 + : 1번 이상 반복 ? : 0번 또는 1번 {n} : 정확히 n번 반복 {n,} : n번 이상 반복 {n,m} : 최소 n번, 최대 m번 반복
저기 위치에 아무것도 안 넣기, keys/values넣기, keys/value하나씩 넣어보기 하다가 튜터님에게 질문하여 알게 되었다.
☑️ GIT
git git rm --cached "레포 파일 삭제" => commit => push해야지 레포에 적용 됨 git rm 삭제할 파일 "파일 자체 삭제" git config --global core.autocrlf true"윈도우 줄바꿈 자동변환" git config --global core.autocrlf false"자동변환 비활성화"
vim에서 탈출 방법 esc누르고 :wq
git 공동 작업 환경 git branch -a 브랜치 이름 학인 git checkout branch-name 특정 브랜치로 이동 git pull origin branch-name 최신파일 가져오기
충돌이 발생했을 때 vim example_file.txt nano example_file.txt code example_file.txt 3개중에 1개로 파일을 열어서 내리다보면 <<<<<<<======>>>>>>으로 표시된 구간에서 이전/지금/ 합쳐서 저장할지 마우스로 클릭하고 저장한 뒤 다시 git add부터 시작하면 된다.
#deck과 embark_town을 fillna(0)로 진행했을 때 TypeError #해결하기 위해 dtype으로 각 데이터 타입을 확인 #숫자형 데이터'0'에서 문자형 데이터'Unknown'으로 대체 #각 타입을 astype(category)과 (object)로 타입 변화 추가해도 안됨 #이유를 찾아보니 원래 카테고리 타입인 데이터에는 새로운 카테고리 값을 추가할 때 에러가 발생 #category 타입 경우 새로운 카테고리를 추가하기 위해선 기존 카테고리 목록에 추가 되어있어야 가능 #또는 타입을 변환을 진행할 때 astype(object)로 작성해서 오류 #astype(str)로 수정 하니 object타입으로 변환 가능
2. 인코딩
# 성별 인코딩: 'male'은 0, 'female'은 1로 매핑 titanic_no_nan['sex'] = titanic_no_nan['sex'].map(lambda x: 0 if x == 'male' else 1 ) # 생존 여부 인코딩: 'yes'는 0, 'no'는 1로 매핑 titanic_no_nan['alive'] = titanic_no_nan['alive'].map(lambda x: 0 if x == 'yes' else 1) # 승선한 항구 인코딩: 'C'는 0, 'Q'는 1, 'S'(Southampton)은 2로 매핑 titanic_no_nan['embarked'] = titanic_no_nan['embarked'].map(lambda x: 0 if x == 'C' else 1 if x == 'Q' else 2) # 승객 등급 인코딩: 'First'는 0, 'Second'는 1, 'Third'는 2로 매핑 titanic_no_nan['class'] = titanic_no_nan['class'].map(lambda x: 0 if x =='First' else 1 if x =='Second' else 2) # 성별에 따른 그룹화 인코딩: 'man'은 0, 나머지(여성)는 1로 매핑 titanic_no_nan['who'] = titanic_no_nan['who'].map(lambda x: 0 if x == 'man' else 1) # 성인 남성 여부 인코딩: 'False'는 0, 'True'는 1로 매핑 titanic_no_nan['adult_male'] = titanic_no_nan['adult_male'].map(lambda x: 0 if x == 'False' else 1) # 갑판 인코딩: 'A'는 0, 'B'는 1, 'C'는 2, 'D'는 3, 'E'는 4, 'F'는 5, 'G'는 6으로 매핑 titanic_no_nan['deck'] = titanic_no_nan['deck'].map(lambda x: 0 if x == 'A' else 1 if x == 'B' else 2 if x == 'C' else 3 if x == 'D' else 4 if x == 'E' else 5 if x == 'F' else 6) # 승선 도시 인코딩: 'Cherbourg'는 1, 'Queenstown'은 2, 'Southampton'은 3, 결측값은 0으로 매핑 titanic_no_nan['embark_town'] = titanic_no_nan['embark_town'].map(lambda x: 1 if x == 'Cherbourg' else 2 if x == 'Queenstown' else 3 if x == 'Southampton' else 0) # 혼자 탑승 여부 인코딩: 'False'는 0, 'True'는 1로 매핑 titanic_no_nan['alone'] = titanic_no_nan['alone'].map(lambda x: 0 if x == 'False' else 1)
#head함수에서 class의 데이터 타입이 category인것으로 확인 #타입 통일을 위해서 astype으로 int 적용해도 category로 나옴 #str을 적용해서 int64로 바뀐것 확인 titanic_no_nan['class'].astype(str)
# 인코딩된 데이터프레임을 titanic_enco 변수에 저장 titanic_enco = titanic_no_nan
#형제,자매, 부부, 부모, 자식의 수는 가족family_size로 묶을 수 있어 데이터 관리에 용이함 #본인을 포함 시켜야 하니 +1 titanic_enco['family_size'] = titanic_enco['sibsp'] + titanic_enco['parch'] + 1
5. 이상치 확인
#이상치를 확인 했지만 특별히 높은 값이 없어 그대로 진행 #모든 열의 이상치 확인
#25%보다 작거나 75%보다 크면 이상치로 처리 #quantile로 이상치의 기준점 설정 for column in titanic_enco.columns: Q1 = titanic_enco[column].quantile(0.25) Q3 = titanic_enco[column].quantile(0.75) IQR = Q3 - Q1
# 이상치 범위 설정 lower_bound = Q1 - 1.5 * IQR upper_bound = Q3 + 1.5 * IQR
#여기서 |는 OR의 논리연산자 #C열의 값중 lower_bound보다 작거나 upper_bound보다 큰 수를 이상치로 간주해 outliers에 저장해서 확인 outliers = titanic_enco[(titanic_enco[column] < lower_bound) | (titanic_enco[column] > upper_bound)]
# 이상치가 있을 경우 출력 # outliers 데이터프레임이 비어 있지 않은지 확인하는 조건문 # empty 속성은 데이터프레임이 비어있으면 True, 데이터가 하나라도 있으면 False를 반환 if not outliers.empty: print(f"Column: {column}") print(outliers[[column]]) # 해당 열의 이상치만 출력 print() # 줄바꿈
# 값이 출력 되었지만 양이 너무 적어보여 GPT에 제대로 작동 한지 검증해서 마지막 열에만 적용 된것을 확인 # 조건문을 활용한 출력 값 코드 이해 X
6. 중복값 확인
#모델 성능 개선을 위해 중복값 존재하는지 확인 후 제거 print(titanic_enco.duplicated().sum())
#데이터 중복값 제거 후 titanic_no_duplicates 변수에 저장 titanic_no_duplicates = titanic_enco.drop_duplicates()
#출력 140
☑️ 모델학습
📚로지스틱 회귀 모델
from sklearn.model_selection import train_test_split from sklearn.preprocessing import StandardScaler from sklearn.linear_model import LogisticRegression from sklearn.metrics import accuracy_score, classification_report, confusion_matrix
# accuracy_score(y_test, y_pred) 실제값 y_test와 예측 값 y_pred를 비교하여 정확도 계산 # classification_report(y_test, y_pred) 모델의 성능을 요약하여 출력(정밀도, 재현율,F1점수, 지원) # confusion_matrix(y_test, y_pred) 혼동 행렬을 생성하여 모델의 성능을 시각적으로 나타낸다. #Precision (정밀도): 모델이 양성으로 예측한 것 중 실제 양성의 비율입니다. #Recall (재현율): 실제 양성 샘플 중에서 모델이 올바르게 예측한 비율입니다. #F1-Score: 정밀도와 재현율의 조화 평균으로, 두 지표의 균형을 잡아줍니다.(높을 수 록 성능이 균형있게 수행 된 것이다.) #평균 Avg 나온 숫자들이 비슷할 수록 좋다. # 혼동행렬: TP, FN, FP, TN #TP (True Positives): 올바르게 긍정으로 예측된 샘플 수 #FP (False Positives): 잘못 긍정으로 예측된 샘플 수 #TN (True Negatives): 올바르게 부정으로 예측된 샘플 수 #FN (False Negatives): 잘못 부정으로 예측된 샘플 수
📚랜덤포레스트 모델
from sklearn.ensemble import BaggingRegressor from sklearn.tree import DecisionTreeRegressor from sklearn.metrics import mean_squared_error from sklearn.model_selection import train_test_split from sklearn.preprocessing import StandardScaler from sklearn.ensemble import RandomForestRegressor from sklearn.metrics import mean_squared_error
rf_model = RandomForestRegressor(n_estimators=100, random_state=42) # 모델 학습 rf_model.fit(X_train_scaled, y_train)
# 예측 y_pred_rf = rf_model.predict(X_test_scaled)
# 평가 mse_rf = mean_squared_error(y_test, y_pred_rf) print(f'랜덤 포레스트 모델의 MSE: {mse_rf}')
# 훈련 데이터에서 예측 y_train_pred = xgb_model.predict(X_train_scaled)
# 훈련 데이터의 MSE 계산 mse_train = mean_squared_error(y_train, y_train_pred) print(f'훈련 데이터에 대한 MSE: {mse_train}')
#MSE는 회귀모델에 적합한 평가모델이기 때문에 좋지 못한 성능으로 나온다. # 0 또는 1로 나뉘는 이진 분류는, MSE가 0.25는 예측이 실제 값에서 평균적으로 0.5 (반쯤 맞고 반쯤 틀림) 정도 #과적합: 훈련 데이터에서 너무 성능이 좋고 테스트 데이터에서 성능이 떨어진다면 과적합의 징후 #0.06 정도 차이로 과적합은 없는듯
📚 XGBoost모델
import pandas as pd import numpy as np import seaborn as sns from sklearn.ensemble import BaggingRegressor from sklearn.tree import DecisionTreeRegressor from sklearn.metrics import mean_squared_error from sklearn.model_selection import train_test_split from sklearn.preprocessing import StandardScaler import xgboost as xgb from sklearn.metrics import mean_squared_error
#deck과 embark_town을 fillna(0)로 진행했을 때 TypeError #해결하기 위해 dtype으로 각 데이터 타입을 확인 #숫자형 데이터'0'에서 문자형 데이터'Unknown'으로 대체 #각 타입을 astype(category)과 (object)로 타입 변화 추가해도 안됨 #이유를 찾아보니 원래 카테고리 타입인 데이터에는 새로운 카테고리 값을 추가할 때 에러가 발생 #category 타입 경우 새로운 카테고리를 추가하기 위해선 기존 카테고리 목록에 추가 되어있어야 가능 #또는 타입을 변환을 진행할 때 astype(object)로 작성해서 오류 #astype(str)로 수정 하니 object타입으로 변환 가능
#map만 사용하였을때 nan값으로 처리 되어서 lambda함수를 같이 사용해야지 된다는 피드백 받음 #그래서 lambda함수를 사용하면 왜 되는건지 찾아봄 #map만 사용했을 땐 사전의 키와 값을 직접적으로 연결하여 변환하기에 간단한 매핑 가능 #lambda함수를 사용하게 되면 복잡한 변환 로직 사용 가능하며 어떤 형식이든 유연히 처리
트리구조를 가지며 내부 노드는 데이터의 특징의 테스트, 가지(brach)는 결과, 리프노드(leaf)는 클래스 레이블을 나타낸다.
📚 데이터 로드 및 전처리
import numpy as np import pandas as pd from sklearn.datasets import load_breast_cancer from sklearn.model_selection import train_test_split from sklearn.preprocessing import StandardScaler
# 데이터 로드 data = load_breast_cancer() X = data.data y = data.target
# 데이터 분할 X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)