728x90

원본 출처:

(1) UoMDSS workshop

https://github.com/UOMDSS/workshops-2022-2023

 

(2) 이미지 이하 내용은 아래 글을 필요한 부분만 추출하여 정리한 것

https://blog.naver.com/PostView.naver?blogId=ycpiglet&logNo=222139077774&redirect=Dlog&widgetTypeCall=true&topReferer=https%3A%2F%2Fsearch.naver.com%2Fsearch.naver%3Fwhere%3Dnexearch%26sm%3Dtop_hty%26fbm%3D0%26ie%3Dutf8%26query%3Dkalman%2Bfilter&directAccess=false


 

자율주행에는, map이 필요함

센서와 데이터를 통한 맵핑(Mapping)이 필요 → 이때 필요한 작업이 바로 '확률 기반의' Localization.

*Localization: 위치 측정

*일종의 추정이론 (Estimation Theory)에 포함되는 것: 입력된 자료가 불완전하거나 불확실하더라도 사용할 수 있는 계산 결과의 근삿값 이용함. 즉, 통계적 방법과 인과관계를 기반으로 예측하는 것. 

 

자율주행차의 Localization의 경우, 필요한 데이터의 전수조사를 할 수 없기에 추정(Estimation) 기법을 동원해야 함.

모든 관측값(Measurement)는 오차(Error)를 가지고 있으며, 기술 통해 줄일 수는 있지만 완전히 없애는 건 불가능함

 

이때 칼만 필터(Kalman Filter)를 활용할 수 있다: current state를 계산할 때 control input으로 사용되는 것

- 적용 대상: GPS, 날씨 예측, 주식 예측 등.

- 칼만 필터의 기본 개념: 과거와 현재의 값을 기준으로 재귀적 연산을 통하여 최적값을 추적하는 것 (상태 관측기의 최적버전)

* 필터: measured data에 포함된 noise를 필터링하는 것 → noise가 포함된 data에서 원하는 신호나 정보를 골라내는 알고리즘

                                                                                      current state를 estimate하는 데 필요함.

- 칼만 필터는 최소제곱법(LSM)을 사용함

- 확률에 기반한 estimation이므로, 예측의 대상은 정규 분포(가우시안 분포)를 가지는 대상.

 

- 적용 상황의 2가지 조건 (1) 모션 모델과 측정 모델이 Linear (2) 정규 분포(가우시안 분포)를 따름

   물체의 measurement에 가우시안분포의 확률적 오차가 포함되고, 특정 시점의 상태가 이전 시점 상태와 선형적 관계를 가진 경우에만 적용이 가능함. 잇따른 한계 존재함.

  예측 model을 이용하여, 자율주행차의 실제 속도와 위치가 어떤 범위에 속할 것이라는 예측(Prediction)이 가능함: 칼만필터는 위치(position)와 속도(velocity) 두 변수를 랜덤 가우시안 분포로 가정함. (estimation != prediction)

 

- 칼만필터의 동작 원리:

   다음 위치를 확률적으로 predict하고,

   실제로 measure한 값을 통해 prediction과 얼마나 비슷한지 확인 후

   보정과 estimate을 한다

    => 재귀적 반복

 

- 칼만필터의 효율성: 일반적인 알고리즘은 기존 데이터를 보유해야 하므로 메모리 부담이 큼. 그러나 칼만필터는 직전 estimation과 현재에 대한 prediction만 저장하고 있으면 되는, 즉 직전값을 제외한 기존의 오래된 데이터는 버려도 되는 '재귀필터'!!

- 칼만필터의 한계: 시스템이 Linear이라는 가정 비선형 시스템에서 error가 커지거나 발산할 수 있음

                             noise가 가우시안 분포를 따른다는 가정 역시 어긋나는 경우가 많음.

 

- 보완책: 확장 칼만 필터(EKF, Extended Kalman Filter): most popular

              무향 칼만 필터(UKF, Unscented Kalman Filter)

              두 가지 모두 적용해보고 성능 비교하여 적용한다고 함.

              파티클 필터(Particle Filter): 추정 확률 분포를 가우시안으로 특정짓지 않는 필터 but 연산량이 많음

 

 

 

 

 

 

 

[수학] 칼만 필터(Kalman Filter)란 무엇인가? (로봇, 자율주행, SLAM 알고리즘)

자율주행(Autonomous Driving)에는 기계(Mobility)가 이동을 하면서 스스로 장애물을 파악해서 피하고, ...

blog.naver.com

 

 

 

 

 

728x90
728x90

1. 주어진 날짜 데이터의 범위 확인

set(data['base_date'].unique())
#21년 9월 1일부터 ~ 22년 8월 31일까지

2. 날짜 데이터의 형태 확인

data['base_data']

# 0         20220623
# 1         20220728
# 2         20211010
# 3         20220311
# 4         20211005
#             ...   
# 291236    20220827
# 291237    20220819
# 291238    20220805
# 291239    20220812
# 291240    20220812
# Name: base_date, Length: 4992458, dtype: int64

=> 년, 월, 일이 분리되지 않은 int64 데이터타입

=> pandas의 to_datetime 함수: 시계열/날짜 데이터 전처리에서 주로 사용되는 함수

     해당 함수는 문자열만을 다루므로, 주어진 날짜 데이터를 문자열로 바꾼 후 to_datetime 함수 적용.

 

3. lamda 활용하여 pandas의 to_datetime 함수 적용

data['basedate_datetime'] = data['base_date'].apply(lambda x: pd.to_datetime(str(x), format='%Y-%m-%d'))
#결과물 확인
data['basedate_datetime'].head 

# bound method NDFrame.head of 0        2022-06-23
# 1        2022-07-28
# 2        2021-10-10
#             ...    
# Name: basedate_datetime, Length: 4992458, dtype: datetime64[ns]> #datetime 형태로 변환됨을 확인

4. 년도, 월, 일, 요일 정보 추출하여 별도의 columns 생성

data['basedate_y'] = data['basedate_datetime'].dt.strftime('%Y') #년
data['basedate_m'] = data['basedate_datetime'].dt.strftime('%m') #월
data['basedate_md'] = data['basedate_datetime'].dt.strftime('%m-%d') #월-일
data['basedate_day'] = data['basedate_datetime'].dt.day_name() #요일
  • 년, 월, 일 : dt.strftime 함수 사용
  • 요일: dt.day_name 함수 사용
  • %Y, %, %m-%d와 같은 코드 활용

출처: https://ivo-lee.tistory.com/90

 

5. 결과물 예시

 

 

 

참고 출처: https://bigdaheta.tistory.com/16, https://acdongpgm.tistory.com/195

728x90
728x90
글 목록
#1 불균형한 데이터 분포 전처리하기
#2 (Random Forest) train-test 분할 및 간단한 모델 학습
#3 Validation 데이터 분할, K-fold 교차검증

1. Validation 데이터 분할

  • 사이킷런의 model_selection의 train_test_split을 활용
    (여기서 'test'이라는 표현에 혼동이 있을 수 있으나 'validation'의 의미로 생각하면 됨)
  • stratify
  • 기존에 train과 test로만 분리된 데이터를 => train, val, test의 세 가지로 나눔
    (train에서 일정 비율을 떼어내 val 데이터로 만듦)
train_x train_y
val_x val_y
test_x test_y

from sklearn.model_selection import train_test_split

X_train, X_val, Y_train, Y_val = train_test_split(train_x, train_y, 
                                                  stratify = train_y, 
                                                  test_size = 0.25, 
                                                  random_state = 10086) 
#'stratify = train_y': train_y에 존재하는 요소의 비율을 고려하여, 검증셋과 훈련셋을 분할함
# 직접 데이터명 지정하여 따로 저장함

아까 방법 그대로. clf 분류기를 학습시켜보자!
이후, (최종 test 데이터에 대한 예측 전), valid 데이터에 대한 예측을 우선적으로 진행해보자.

clf = RandomForestClassifier()
clf.fit(X_train, Y_train)
Y_proba = clf.predict_proba(X_val) #학습한 분류기의 예측 결과

val 데이터에 대한 모델의 예측 점수(성능)을 계산해보자.

  • 사이킷런의 함수 통해 점수 반환하려면, Y_val을 원핫인코딩 형태로 변환해야 함.
    pandas의 get.dummies()
  • val에 대한 점수 반환해보기
    사이킷런의 metrics의 log_loss 함수 이용
    log_loss(정답, 예측값)
Y_val_onehot = pd.get_dummies(Y_val) #실제 정답지의 원핫인코딩 버전

from sklearn.metrics import log_loss #val에 대한 logloss 점수 반환
log_loss(Y_val_onehot, Y_proba)

2. K-fold 교차검증

2.1 Fold 생성

상대적으로 데이터량이 충분하지 않은 경우, 머신러닝에서는 나에게 주어진 데이터를 얼마나 효율적이고 효과적으로 사용해내느냐가 중요하다. 이때 활용할 수 있는 것이 'K-fold 교차검증'이다.

  • 과적합 방지 위한 툴
  • 데이터를 k개의 폴드로 쪼개어 하나씩 돌아가며 valid data를 수행함 => k개 경우의 성능 평균을 산출
  • 사이킷런의 model_selection에서 (Stratified)KFold 사용
    StratifiedKFold(n_splites = n, shuffle = True, randome_state = n)
    각 데이터의 인덱스 숫자를 기준으로.
from sklearn.model_selection import StratifiedKFold 
#단순 KFold를 사용할 수 있지만 stratified가 추가된 버전을 사용하자!

folds = StratifiedKFold(n_splits=5, shuffle=True, random_state=55) 
#KFold 생성기 생성=> 이후 folds.split(~)과 같은 방식으로 데이터를 쪼갬

잠깐, StratifiedKFold가 어떠한 방식으로 데이터를 쪼개는지 간단히 살펴보자.
K개의 폴드가 생성되므로, 쪼개는 경우의 수 역시 K일 것이다. 그 가운데 첫 번째 경우는 이하와 같이 쪼개진다.

(array([ 0, 1, 2, ..., 26454, 26455, 26456]), #train_index에 해당
array([ 4, 12, 23, ..., 26442, 26443, 26446])) #val_index에 해당

따라서 iloc을 이용하면 train에 해당하는 데이터와 val에 해당하는 데이터를 '인덱스'를 기준으로 쪼갤 수 있다.
KFold를 생성하고 각 경우에 대한 학습 성능을 산출하는 일련의 과정을 for문으로 합쳐보자.

2.2 for문으로 합치기: 각 폴드에서의 예측 점수를 반환

  • enumerate : 출력되는 현재 for문에 몇번째에 대한 for문인지 알려줌
  • 각각의 학습이 서로 독립적으로 이루어지도록, classifier를 매번 새롭게 선언해야 함.
  • 문자열 formatting 문법 기억!"%d번째 학습 결과는 %.4f점 입니다.\n\n"%(n_fold+1,score)
    https://studymake.tistory.com/179
scores = []
n_splits=5
folds = StratifiedKFold(n_splits=5, shuffle=True, random_state=55)

#각각의 학습이 서로 독립적으로 이루어지도록, classifier를 매번 새롭게 선언해야 함.
for n_fold, (train_index, val_index) in enumerate(folds.split(train_x, train_y)):
  X_train, X_val = train_x.iloc[train_index], train_x.iloc[val_index]
  Y_train, Y_val = train_y.iloc[train_index], train_y.iloc[val_index]
  clf = RandomForestClassifier()
  clf.fit(X_train, Y_train)
  Y_val_proba = clf.predict_proba(X_val)
  Y_val_onehot = pd.get_dummies(Y_val)
  score = log_loss(Y_val_onehot, Y_val_proba)
  print("%d번째 학습 결과는 %.4f점 입니다.\n\n"%(n_fold+1,score))
  scores.append(score)

  if n_fold+1 == n_splits:
    avg_score = sum(scores)/n_splits #numpy통해 np.mean(scores)로 바로 구할 수 있음.
    print("평균 점수는 %.4f점 입니다!"%avg_score)
    break

>>> 1번째 학습 결과는 1.0524점 입니다.
2번째 학습 결과는 1.0799점 입니다.
3번째 학습 결과는 1.1412점 입니다.
4번째 학습 결과는 1.0329점 입니다.
5번째 학습 결과는 1.0653점 입니다.
평균 점수는 1.0743점 입니다!

2.3 최종 Test (앙상블)

KFold를 사용함에 따라, 주어진 데이터로 총 K번의 서로 다른 학습을 진행할 수 있게 되었다.
이같은 방식으로 랜덤포레스트 classifier를 튜닝하고, 더 좋은 성능의 모델을 만들 수 있다.
=> 이때 각 fold별 모델을 test 데이터에 대한 추론으로 바로 사용하여 제출물을 만들 수도 있다. (= 앙상블)
=> 1개밖에 없던 분류기를 -> k개로 늘린 것 -> val은 각 분류기의 성능을 대략 예측해줌 -> 동일한 test 데이터에 대해 각 분류기가 k가지의 서로 다른 예측 결과를 반환함  

➡️모델 전체에 대한 최종 성능 = mean(k개의 성능 점수)  
➡️모델이 test에 대해 최종 예측한 결과 = mean(k개의 예측 결과)

scores = []
sub = np.zeros((test_x.shape[0],3)) # 제출해야 하는 값: test_x의 row X 3개의 columns

#각각의 학습이 서로 독립적으로 이루어지도록, classifier를 매번 새롭게 선언해야 함.
for n_fold, (train_index, val_index) in enumerate(folds.split(train_x, train_y)):
  X_train, X_val = train_x.iloc[train_index], train_x.iloc[val_index]
  Y_train, Y_val = train_y.iloc[train_index], train_y.iloc[val_index]
  clf = RandomForestClassifier()
  clf.fit(X_train, Y_train)
  Y_val_proba = clf.predict_proba(X_val)
  Y_val_onehot = pd.get_dummies(Y_val)
  
  sub += clf.predict_proba(test_x) #얘랑

  score = log_loss(Y_val_onehot, Y_val_proba)
  scores.append(score) #얘랑 구분하기!!

sub = sub / 5
np.mean(scores) #fold별 추론 값들의 평균 (다섯 번의 추론 결과 평균)
sample_submission.to_csv("5fold_prediction.csv", index=False)


출처
https://www.youtube.com/watch?v=fBBHiShcJZo&list=LL&index=3

가쟈가쟈가쟈~

728x90
728x90
#1 불균형한 데이터 분포 전처리하기
#2 (Random Forest) train-test 분할 및 간단한 모델 학습
#3 Validation 데이터 분할, K-fold 교차검증 

1. train-test 분할

(1) 기존에 train과 test 데이터를 한꺼번에 전처리시키기 위하여 -> 각각을 'data'라는 이름의 데이터프레임으로 합침

data = pd.concat([train,test], axis=0)

(2) 이후 결측치 제거하고, 불균형한 데이터에 대한 전처리(이전 포스트)를 진행함

data.isnull().sum() 
data = data.drop("occyp_type", axis=1)
#data 데이터프레임에 이를 반영 #concat에서의 문법과 비교할 것.

(3) 전처리가 끝나면, 모델 학습을 시작함 => 전처리가 반영된 data를 train용과 test용으로 다시 분리해야 함.

train.shape
test.shape #기존 train 및 test 데이터의 크기 파악
data.shape #전처리 반영된 data의 크기 파악

train = data[:-10000] #데이터프레임 인덱싱에서 :는 column이 아닌 row만! #train에 해당
test = data[-10000:] #test에 해당

(4) train과 test 데이터 각각, 클라스 정보와 라벨 정보(정답)을 분리

#train
train_x = train.drop("credit", axis=1) #credit column을 제외한 train
train_y = train["credit"]
#test
test_x = test.drop("credit", axis=1)
test_y = test["credit"]
* 데이터프레임 인덱싱에서 loc 유의사항
train.loc[:"credit"]이라고 하면, 전체 행 X credit까지의 열: 즉 표 전체가 출력됨
특정 column만 추출하고 싶다면, train.loc[:,"credit"]과 같이 콤마를 추가해야 함

 

2. Random Forest

트리 기반 앙상블 모델 (사이킷런에서 제공하는 머신러닝 툴)
RandomForestClassifier()
분류기.fit 메소드
분류기.predict_proba 메소드
numpy의 np.argmax(예측확률, axis = 방향)

 

(1) RandomForest 분류기 생성한 후 이것으로 학습 진행

from sklearn.ensemble import RandomForestClassifier
clf = RandomForestClassifier() #랜덤 포레스트 분류기 생성

clf.fit(train_x, train_y) #이미 정답이 주어진 train 데이터에 대해서는, fit을 통해 학습시킴
# 결과를 따로 저장할 필요 없이, 내부에 스스로 저장됨

(2) test_x에 대한 예측 및 결과 저장

학습된 분류기를 test_x에 적용하여, 예측 결과 반환
test_proba = clf.predict_proba(test_x)
print(test_proba)

#데이콘 원칙 상, 주어진 sample_submission에 아래 예측 결과를 집어넣어야 함.
sample_submission.iloc[:,1:] = test_proba

해당 예측 결과를 csv 파일로 변환
데이터프레임.to_csv("파일명")

sample_submission.to_csv("sample_submission_ver1.csv", index=False)

 

출처:

https://www.youtube.com/watch?v=AWfgyln0EOM 

모두 데이콘 합시다아

728x90
728x90
#1 불균형한 데이터 분포 전처리하기
#2 (Random Forest) train-test 분할 및 간단한 모델 학습
#3 Validation 데이터 분할, K-fold 교차검증 

1. 분포 상태 확인 후 그룹화

 data.apply(lambda x : len(x.unique()))

모든 인덱스에 대한 값을 한꺼번에 반환하기

  • apply: 데이터프레임["컬럼"].apply(함수명)=> 해당 함수를 우리가 기존에 정의한 데이터프레임 중 A컬럼에 대해 적용df['A'].apply(plus_one) / df['A'].apply(lambda x : x+1)
  • lambda: lambda 매개변수 : 표현식 => 함수를 딱 한 줄만으로ex. (lambda x,y: x + y)(10, 20)
  • len, unique메소드 이용 : unique는 데이터에 고유값들이 어떠한 종류들이 있는지 알고 싶을때 사용하는 메소드

https://wikidocs.net/64
https://koreadatascientist.tistory.com/115
https://jaaamj.tistory.com/112

 

2. 요소 개수를 기준으로 세 개의 그룹으로 분할

2.1 group_1: 2개 이하

이진변수 인코딩(0과 1로 표현)

data['gender'] = data['gender'].replace(['F', 'M'], [0, 1])

 

2.2 group_2: 2개 초과 10개 이하

(연속형 숫자) 극소수의 2초과 값 모두 2로 변환
data.loc[data['child_num']>2, 'child_num'] = 2​

(문자) sklearn의 preprocessing 가운데 LabelEncoder()를 통해 문자형 카테고리를 숫자형으로 변환
label_encoder = preprocessing.LabelEncoder()

for x in ['income_type', 'edu_type', 'family_type', 'house_type']:
  data[x] = label_encoder.fit_transform(data[x])
  print(data[x].unique,"\n---")​

 

2.3 group_3: 10개 초과

(연속형 숫자, 요소 종류가 아주 많을 때)
마찬가지 구간화하되 group_2처럼 통일시키는 게 아니라 구간을 여러 개로 만들어버림:
- numpy의 histogram 메소드(bins=) 통해 bin_dividers 생성
- pandas의 cut 메소드(bins=) 통해 데이터를 실제로 분할
- 그러나 위 결과는 연속형이 아닌 이산형 dtype이므로 pandas의 factorize 함수 통해 int로 변환
=> 일련의 과정을 하나의 함수로 단순화하기.
def make_bin(array, n):
  array = -array #대부분의 요소가 음수이므로 양수로 변환 ★★★
  _, bin_dividers = np.histogram(array, bins = n)
  cut_categories = pd.cut(array, bins = bin_dividers, include_lowest = True, 
                          labels = list(range(n)))
  bined_array = pd.factorize(cut_categories)[0]
  return bined_array​

*value_counts나 plot 사용하려면 numpy-array가 아닌 pandas-Series 형태여야 함. => pd.Series(~)

 

https://www.youtube.com/watch?v=AWfgyln0EOM 

모두 데이콘 합시다아

728x90

+ Recent posts