반응형

AI에게 이미지를 생성하라고 해 본 결과.....

아래 생성한 이미지의 프롬프트는...   

anime girl, long light gold hair, splendid white designer fashion show concept dress, red cosplay headwear, black scarf, body portrait, red eyes, pink ribbons, slight smile, black constellation motif, windy, concept art, mini tornado stickers, black fishnet wear, highly detailed, digital painting, artstation, concept art, sharp focus, illustration, art by WLOP and greg rutkowski and alphonse mucha and artgerm and yanjun chen

 

 

 

아.. 이건 처음으로 프롬프트 아무거나 달과 지구 사진을 달라고 테스트 해 본 거입니다.

 

 

'AI(DeepLearning)' 카테고리의 다른 글

[ChatGPT] 글쓰기  (0) 2023.02.09
[ChatGPT] 글쓰기 테스트  (1) 2023.02.09
XGBoost 요약  (0) 2019.12.06
처음해본 kaggle 도전기  (1) 2019.11.27
Custom EarlyStopping  (0) 2019.11.11
반응형

아래 글은 ChatGPT가 작성하게 해 본 겁니다. 내용이 정확하지 않을 수 있으니, 조심하세요...

요약 : 기본 사항을 이해하고, 적절한 형태를 사용하고, 점차적으로 체중 증가, 부피 증가, 변화, 영양에 중점을두고 휴식을 취함으로써 데 드리프트 체중을 증가시킵니다.

"## 데드 리프트 체중을 신속하게 늘리기 위해 어떻게 운동합니까?

img

데드 리프트는 힘과 힘을 얻기위한 가장 중요한 연습 중 하나입니다. 또한 마스터하기 가장 어려운 운동 중 하나입니다. 모든 운동과 마찬가지로 데드 리프트 체중을 늘리려면 일관성을 높이고 운동을 올바르게 수행해야합니다. 이 기사는 데 드리프트 체중을 신속하게 늘리기 위해 운동하는 방법에 대한 팁을 제공합니다.

기본 사항을 이해하십시오

데드 리프트 체중을 늘리기 시작하기 전에 운동의 기본 사항을 이해하는 것이 중요합니다. 운동의 적절한 형태와 기술뿐만 아니라 데드 리프트에 사용되는 근육을 알아야합니다. 이렇게하면 이익을 극대화하고 부상을 예방하는 데 도움이됩니다.

적절한 형태를 사용하십시오

데드 리프트를 수행 할 때는 적절한 형태를 사용하는 것이 중요합니다. 형태는 일관성이 있어야하며 올바른 근육을 참여시키는 데 집중해야합니다. 올바른 양식을 사용하지 않는 경우 적절한 형태로 최대한 많은 무게를 들어 올릴 수 없습니다.

체중을 점차적으로 증가시킵니다

데드 리프트의 무게를 늘리면 점차적으로 수행하는 것이 중요합니다. 이로 인해 부상을 입을 수 있으므로 체중을 너무 빨리 증가시키지 않아야합니다. 편안한 체중으로 시작하고 더 강해지면서 체중을 점차적으로 증가시킵니다.

볼륨 증가

데드 리프트 체중을 빠르게 늘리려면 운동량을 늘리는 것이 중요합니다. 이것은 운동의 더 많은 세트와 담당자를 수행하는 것을 의미합니다. 운동량을 늘리면 근육과 힘을 키우는 데 도움이됩니다.

변형을 사용하십시오

표준 데 드리프트를 수행하는 것 외에도 일상에 변형을 통합해야합니다. 이것은 운동을 흥미롭고 도전적으로 유지하는 데 도움이 될 수 있습니다. 데드 리프트의 변화는 다른 근육을 목표로하는 데 도움이 될 수 있습니다.

영양에 중점을 둡니다

영양은 힘을 얻고 데 드리프트 체중을 증가시키는 데 중요한 요소입니다. 균형 잡힌 식단을 먹고 충분한 단백질을 섭취하면 근육을 키우고 운동을 지원하는 데 도움이됩니다.

나머지

휴식은 모든 운동 루틴의 중요한 부분입니다. 휴식은 근육이 회복하는 데 도움이되며 부상을 예방하는 데 도움이됩니다. 운동 사이에 충분한 휴식을 취하십시오.

이 팁을 따르면 데드 리프트 체중을 신속하게 늘릴 수 있어야합니다. 적절한 형태를 사용하고 체중을 점차적으로 늘리는 것을 잊지 마십시오. 변형을 사용하여 운동을 흥미롭게 유지하고 영양에 초점을 맞추십시오. 마지막으로 운동 사이에 휴식을 취하십시오."

'AI(DeepLearning)' 카테고리의 다른 글

[SD] 이미지생성  (0) 2023.02.09
[ChatGPT] 글쓰기 테스트  (1) 2023.02.09
XGBoost 요약  (0) 2019.12.06
처음해본 kaggle 도전기  (1) 2019.11.27
Custom EarlyStopping  (0) 2019.11.11
반응형

아래 정보. 생성한 글, 요약한 정보, 해시태그까지 모두 ChatGPT로 한 결과입니다.
꽤 그럴싸한 정보들인데 가끔 틀린 정보들도 있으니 조심해야 됩니다. ㅎㅎㅎ

요약: 낮은 무게, 적절한 형태, 일관된 훈련, 기타 운동, 휴식 및 균형 잡힌식이 요법으로 벤치 프레스 체중을 점차적으로 증가시킵니다.

벤치 프레스 무게를 늘리는 방법

img

벤치 프레스는 심각한 리프터에게 가장 중요한 연습 중 하나입니다. 상체 운동의 필수 부분이며 근육, 힘 및 크기를 만드는 데 도움이 될 수 있습니다. 그러나 벤치 프레스 무게를 늘리는 데 어려움이 있다면 다음과 같은 도움을 줄 수있는 몇 가지 팁이 있습니다.

팁 1 : 양식에 중점을 둡니다

벤치 프레스 체중을 높이기 위해 할 수있는 가장 중요한 일은 적절한 형태에 집중하는 것입니다. 올바른 형태를 갖추면 올바른 근육을 사용하고 리프트를 최대한 활용할 수 있습니다. 등이 평평하고 발이 땅에 단단히 심어지고 팔꿈치가 옆구리에 집어 넣어야합니다.

팁 2 : 그립 강도를 높이십시오

그립 강도는 벤치 프레스 무게를 늘리는 데 필수적입니다. 그립 강도를 향상 시키려면 농부의 산책, 손목 컬 및 바벨 행과 같은 운동을하십시오. 그립 강도를 사용할 수도 있습니다. 그립 강도는 그립 강도를 높이도록 도와줍니다.

팁 3 : 복합 운동을 사용하십시오

복합 운동은 한 번에 여러 근육 그룹을 대상으로하는 운동입니다. 복합 운동은 강도와 ​​힘을 구축하는 데 적합하며 벤치 프레스 무게를 높이는 데 도움이됩니다. 복합 운동의 일부 예로는 스쿼트, 데드 리프트 및 오버 헤드 프레스가 있습니다.

팁 4 : 삼두근을 훈련시킵니다

당신의 삼두근은 누를 때 막대를 밀어 넣는 근육입니다. 벤치 프레스 무게를 늘리려면 삼두근을 훈련시켜야합니다. 이를위한 훌륭한 운동은 근접 그립 벤치 프레스, 딥 및 삼두근 푸시 다운입니다.

팁 5 : 볼륨을 높이십시오

볼륨을 높이는 것은 벤치 프레스 무게를 늘리는 좋은 방법입니다. 볼륨은 주어진 운동에서 수행하는 총 세트 및 담당자 양을 나타냅니다. 벤치 프레스 볼륨을 높이려면 세트 당 더 많은 세트를 수행하거나 세트 당 담당자 수를 늘릴 수 있습니다.

팁 6 : 충분한 단백질을 먹습니다

충분한 단백질을 섭취하는 것은 근육과 힘을 구축하는 데 필수적입니다. 단백질에는 근육의 빌딩 블록 인 아미노산이 들어 있습니다. 벤치 프레스 무게를 늘리려면 매일 충분한 단백질을 섭취하십시오.

팁 7 : 충분한 수면을 취하십시오

마지막으로, 벤치 프레스 무게를 늘리기 위해서는 충분한 수면을 취하는 것이 중요합니다. 잠을 자면 신체는 근육 조직을 수리하고 에너지 저장을 보충합니다. 충분한 수면을 취하려면 밤에 7-9 시간을 목표로하십시오.

이 팁을 따르면 벤치 프레스 무게를 즉시 늘릴 수 있어야합니다. 행운과 행복한 리프팅!

'AI(DeepLearning)' 카테고리의 다른 글

[SD] 이미지생성  (0) 2023.02.09
[ChatGPT] 글쓰기  (0) 2023.02.09
XGBoost 요약  (0) 2019.12.06
처음해본 kaggle 도전기  (1) 2019.11.27
Custom EarlyStopping  (0) 2019.11.11
반응형
XGBoost

XGBoost

eXtreme Gradient Boosting

  • 병렬 처리로 학습, 분류 속도가 빠르다.
  • 다양한 옵션. Customizing 용이
  • Greedy 알고리즘을 사용한 자동 가지치기로 오버피팅 방지가 된다.
  • 다른 알고리즘과 연계에도 성능이 좋다. 뒷단에 다른 레이어 추가.

XGBoost는 딥러닝이 아니다. 여러가지 조건문들이 들어가는 가지치기로 보면 된다. Decision Tree라고 하고 이것들이 다 모이면 최종적으로 forest라고 한다
데이터에 따라 딥러닝보다 성능이 좋은 경우가 많다.

XGBoost는 CART(Classification and regression tree) 앙상블 모델을 사용한다. 모델끼리의 우의 비교를 통해 최종 결정을 내림.

파라미터

  • 일반 파라미터 ; 어떤 모델을 쓸 것인가?
    • gbtree, gblinear, dart
    • nthread ; 쓰레드 수. 디폴트는 max
    • num_feature ; 입력 차원. 디폴트는 max
  • 부스터 파라미터 ; 트리마다 가지치기 옵션
    • eta ; learning rate. 트리에 가지가 많을수록 과적합 발생.
    • gamma ; 정보획득에서 -r. 값이 클수록 트리 depth가 줄어든다. 디폴트는 0
    • max_depth ; 한 트리의 최대 깊이. 클수록 복잡도가 커짐. 즉, 과적합. 디폴트는 6으로 리프노드의 최대개수는 64가 된다.
    • lambda ; L2 Regularization. 클수록 보수적.
    • alpha ; L1 Regularization
  • 학습 과정 파라미터 ; 최적화
    • objective ; 목적함수. reg:linear, binary:logistic, count:poisson 등
    • num_rounds : 라운드 epoch 같은 개념. 너무 커도 좋지 않다.

파라미터를 알아야 모델을 구축할 수 있다.
binary classification 문제에 linear-regression을 적용하면 아무리해도 답이 안나온다.

  • 민감한 정도로 먼저 조정해야 될 것들
    • booster 모양
    • eval_metric(평가함수)/ objective(목적함수)
    • eta (epoch)
    • L1
    • L2

Sample1. XGBClassifier

from numpy import loadtxt
from xgboost import XGBClassifier
from xgboost import plot_importance
from matplotlib import pyplot

dataset = loadtxt('pima-indians-diabetes.csv', delimiter=',')
x=dataset[:,0:8]
y=dataset[:,8]

# fit model no training data
model = XGBClassifier()
model.fit(x,y)

plot_importance(model)
pyplot.show()
  • fitting후 plot_importance로 어떤 피쳐들의 중요도를 높게 보고있는지 막대그래프로 확인할 수 있다.
  • 중요도가 크게 떨어지는 피쳐들은 삭제하는 것이 성능에 좋은 영향을 주는 경우가 많다.

Sample2. XGBRegressor

import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import Imputer

# 데이터를 읽고, null 레코드 삭제
data = pd.read_csv('../input/train.csv')
data.dropna(axis=0, subset=['SalePrice'], inplace=True)
# 출력값은 집값
y = data.SalePrice
# 훈련데이터에서 집값제거하고 수치가 아닌 데이터 삭제.
X = data.drop(['SalePrice'], axis=1).select_dtypes(exclude=['object'])
# 데이터 분리. train, validation data. 
train_X, test_X, train_y, test_y = train_test_split(X.as_matrix(), y.as_matrix(), test_size=0.25)

# 데이터 전처리
my_imputer = Imputer()
train_X = my_imputer.fit_transform(train_X)
test_X = my_imputer.transform(test_X)

  • sklearn의 preprocessing에 Imputer로 데이터를 전처리 하였다.
  • Imputer?
    • 누락 NA 데이터에 대한 전처리가 가능하다.
    • 데이터 파일에서 ‘na’ 스트링을 na로 인식하여 로딩하여도록 하려면 pd.read_csv(‘test.csv’, na_values=‘na’)
  • SimpleImputrer
    -누락된 데이터의 값을 특정 값으로 지정하거나 통계값으로 설정할 수 있다.
    • imp = SimpleImputer(missing_values=np.nan, strategy=‘mean’)
    • imp.fit( data ) ; fitting하여 통계 정보를 구한다.
    • X = imp.transform( data ) ; 위 통계 정보를 사용하여 np.nan값을 컬럼마다 평균값으로 채움.
    • missing_values=-1 로 하면 -1값을 누락값으로 인식.
    • strategy의 종류 ; mean, most_frequent (최고빈도로 스트링 컬럼(category)도 처리가 됨.)
  • Imputer
    • Imputer(missing_vaues=‘NaN’, strategy=‘mean’ , axis=0, verbose=0, copy=True) ; 기본값 확인. (여기는 특이하게 axis=0이 컬럼방향이다.)
from xgboost import XGBRegressor

my_model = XGBRegressor()
# Add silent=True to avoid printing out updates with each cycle
my_model.fit(train_X, train_y, verbose=False)

# make predictions
predictions = my_model.predict(test_X)

from sklearn.metrics import mean_absolute_error
print("Mean Absolute Error : " + str(mean_absolute_error(predictions, test_y)))
  • 학습은 위와 같이 매우 간단하다.

모델 튜닝

  • 성능을 올리기 위한 필수 과정.
  • n_estimators ; 학습 횟수
  • early_stopping_rounds ; n연속으로 발전(기존 max 갱신)이 없으면 강제 중지
my_model = XGBRegressor(n_estimators=1000)
my_model.fit(train_X, train_y, early_stopping_rounds=5, 
             eval_set=[(test_X, test_y)], verbose=False)
  • learning_rate ; 학습률
my_model = XGBRegressor(n_estimators=1000, learning_rate=0.05)
my_model.fit(train_X, train_y, early_stopping_rounds=5, 
             eval_set=[(test_X, test_y)], verbose=False)
  • n_jobs ; 병렬처리로 보통 cpu core 수로 정하는 것이 좋다.

Author: crazyj7@gmail.com

'AI(DeepLearning)' 카테고리의 다른 글

[ChatGPT] 글쓰기  (0) 2023.02.09
[ChatGPT] 글쓰기 테스트  (1) 2023.02.09
처음해본 kaggle 도전기  (1) 2019.11.27
Custom EarlyStopping  (0) 2019.11.11
타이타닉 kaggle 자료 분석  (0) 2019.08.23
반응형
crazyj_kaggle_first

Kaggle first time

crazyj7@gmail.com

동기

처음에 이 사이트를 보고 단순히 무료로 데이터 파일들을 다운받을 수 있는 사이트 인줄 알았다. 거의 방문을 안하다가 가끔 데이터 파일 쓸모있는게 있나 찾다가 여러가지 다른 기능들이 많은 것을 발견했다.
학습에 도움이 많이 될 거라는 생각에 모니터링 중 Competition이 있는 것을 알게 되고 국내에서 주최한 대회가 있다는 것에 흥미를 느끼고 장난삼아 도전해 보려고 했다.
그간 AI쪽을 제대로 공부한 적은 없지만 나름대로 독을 좀 했. 다만 혼자서 하려니 어디 물어볼 데도 없고, 이해가 안가서 막히는 것들이 많아 진행 속도가 더디었다.

캐글 사용기

커널을 대체 어떻게 사용해야 되는지 어렵다.
느리고, 자꾸 끊기고, 에러나고, 아웃풋을 못찾겠고, 이어서 되는 건지 아닌지 모르겠고. 커밋은 git 처럼 소스 커밋을 말하는 건지…

  • 커널을 여러 개 동시에 돌릴 수 있다고 한다. 최대 5개 던가? 아직 해 보지는 않았다.
    • 3개 4개 돌려보니 잘 된다. 계속 하다 보면 익숙해짐.
  • 커널 이용 최대시간은 9시간 이라고 하는 것 같다. 학습이 이 시간을 넘어가면 짤린다는 것이겠다. 중간 저장이 필수겠다.
  • 가공 생성한 파일들은 대체 어디에 있는 것일까?
    • 현재 디렉터리에 생성된다. /kaggle/working 인 듯. 디렉터리 탐색도 커맨드 실행으로 할 수 있다. 커널버전 보기에서 Output 메뉴에 생성한 파일들 목록이 보여서 다운로드는 할 수 있다.
    • 그런데 이어서 작업할 때는 왜 output 파일이 다 없어지는 것일까? 디렉터리 탐색시 다 사라진다. 작업 디렉터리인 working 디렉터리는 세션 실행시 초기화된다. output이 다 없어진다. 주의! 이전 커밋은 버전을 찾아 들어가면 output을 받을 수 있다.
  • 소스는 여러 개를 올릴 수 있는 것일까?
    • 안되는 것 같다.
    • 한 파일만 되는 듯. ipynb (노트북)와 py(스크립트) 변환을 지원하고 업로드기능이 있으니 잘 활용하면 된다. 스크립트는 올릴필요없이 복붙하면 쉽다.
  • 대체 커밋이 뭐지?
    • 커밋은 소스 전체를 실행하는 것이다. 에러없이 모두 성공해야지만 output 파일이 생성되고, 다운 받을 수 있다. 중간에 실패하면 날라간다. ㅜ.ㅜ
  • 생성한 output을 유지할 수는 없나?
    • 시행착오 끝에 output을 다운 받아서 dataset에 추가하고 커널에서 dataset을 추가해서 불러서 사용하면 된다.
  • 데이터셋 업데이트는?
    • 안된다. 올라간 데이터셋을 삭제하고, 새로운 데이터셋을 동일한 이름으로 올리는 식으로 업데이트 할 수 있다. 불편함. 해당 데이터셋을 참조하는 커널에서는 링크깨진 데이터셋을 삭제하고 다시 만든 것을 추가해 주어야 한다.

캐글 사용 정리

  1. 로컬 환경에서 먼저 자료 분석을 한다.
    데이터 셋을 받은 다음 jupyter notebook이나 lab으로 자료 관찰하고, 데이터 전처리를 하는 것을 만든다.
  2. 데이터 전처리된 파일들을 데이터셋으로 만들어 업로드한다.
  3. 가급적 경로를 로컬환경과 캐글환경을 일치시키면 올릴때 경로 수정이나 환경플래그값을 변경하지 않아도 되어 편하다.
    따라서 …/input/dataset이름/파일명 이나 …/input/dataset이름/압축파일명/내부파일명 으로 접근.
  4. 커널을 만들고 데이터셋을 추가하여 테스트해 본다
  5. 로컬 환경에서 디버그 모드를 만들어 적은 데이터로 빠르게 학습할 수 있도록 준비한다. 잘 되면 릴리즈모드로 만들고 커널에 임포트하여 커밋해 본다.
  6. 기본이 되는 커널을 잘 만든다. 여러가지 테크닉을 집어 넣기 전에 기본이 되는 커널이 잘 작동하고 성능도 좋게 만들 방안을 찾는다.
  7. 데이터가 크면 메모리 부족 에러를 아주 많이 볼 것이다. 이미지의 경우 numpy로 만들어 로딩하여 쓰다 보면 그리고 data type을 float로 변환하면 엄청나게 증가한다. 미리 메모리에 로딩하지 말고 필요한 만큼. 일정 크기만큼 불러서 처리하고 결과 저장하고를 반복하여 메모리 부족을 방지해야 한다. 전처리 후 이미지 크기도 크게 영향을 받는다. 이미지가 너무 작으면 성능이 떨어질 것 같고, 너무 크면 학습도 어렵고 메모리도 부족할 것 같다.
  8. EarlyStopping을 사용하여 멈출 때를 정한다. metric을 평가 방식에 맞게 설정한다. (loss, acc, f1_score 등)
  9. Checkpoint 저장. 중간 중간 best를 계속 저장하도록 한다.
  10. 테크닉?
  • 이미지 전처리를 바꿔본다. 크기, Margin추가, 색상, color scale, … cut-out (이미지 일부를 삭제), normalize, …
  • Image Augument Generator로 학습 데이터를 늘린다. zoom, shift, rotation, shear, flip, brightness, …
  • Pre-Trained Model 변경 : xception, efficientnet, resnet, …
  • Dropout 추가
  • Train/Validation 비율 변경 / 샘플링 기법 변경 : oversampling, straitifiedKFold, …
  • ReduceLROnPlateau 적용
  • Cross Validation : 결국 모든 학습데이터를(validation 포함) 훈련하게 되는 방식으로 학습데이터가 많아서 결과도 더 좋아진다.
  • 앙상블 : 여러 네트웍의 결과를 보고 판단. (5% 정도 올랐음)
  • TTA : 시험시에 시험 이미지에 Augument를 가해서도 측정해 보고 그 결과를 반영해 본다. (0.2% 올랐음)
  1. 몇 개의 폴드로 나눠서 폴드 번호를 지정하고 학습할 수 있는 스크립트를 만들고, 커널에 올려 돌린다. 이 커널을 Fork하여 폴드 번호를 바꿔가면서 계속 커널을 만들어 commit한다. 동시에 4개까지 model을 만들 수 있을 것이다.
  2. model들을 다운 받아 모델 데이터셋을 만든다.
  3. 모델들을 합쳐 앙상블 결과를 내는 스크립트를 만들어 돌린다.
  4. 마지막에 TTA를 추가해 본다.
  5. pseudo labeling 적용 테스트. (효과가 있을지는 모르겠다.)

용어

  • val ; validation. 검증용 데이터. 모델 학습시에는 모델은 검증 데이터를 전혀 본적없는 데이터이다.
  • k fold ; train, val 셋을 분리하는데, k개의 다른 방식으로 데이터를 나눈다. 따라서 fold별로 하나씩 모델을 만들 수 있다.(k개의 모델 생성 가능). 나중에 생성된 모델들을 합친다(? 앙상블한다는 의미인가?)
  • stratifiedkfold ; kfold를 할 때, 원본 데이터의 클래스 비율을 유지하여 분리한다.
  • oversampling / undersampling ; stratified하는 것 대신, 샘플 수를 고르게 맞추는 방식이다. over는 많은 개수 기준. under는 부족한 개수 기준.
  • tta ; 학습시가 아닌 테스트시에 augmentation을 하여 앙상블 결과를 내놓는다.
  • cross validation ; 학습이 다 끝나면 나중에 validation data도 학습한다.
  • 앙상블 ; 여러 다른 모델의 결과를 합친다. (? 합치는 방식이 여러가지 일 듯. average, max count)
  • pseudo label ; 어느정도 성능이 나온 훈련모델로 test셋의 결과를 예측하여 99% 가량 강하게 맞다고 한 데이터의 라벨을 가상으로 붙여 훈련셋에 추가한다. 훈련데이터 개수 확장 효과.
  • cut-out image ; 이미지에서 랜덤하여 자름. 랜덤한 영역의 블록을 잘라버림. (노이즈)
    -했다면 했다고 할 수 있다.

Car model classify

문제는 자동차 모델명을 분류하기.
학습 이미지 데이터와 라벨이 있고 더구나 Bounding box도 있어서 도전해 볼만 했다. 근데 클래스가 상당히 많았다. 정확도가 높게 나오지 않을 것 같은데…라는 생각이 들었다. 그러나 나중에 보니 다른 참가팀들의 정확도에 놀랐을 뿐이다.

Try1 ; 70%

  • mobilenetv2

전에 한 번 구글이미지 검색으로 동물들 데이터셋을 만들어 이미지 분류 테스트를 해봤었는데 단순한 몇 개 클래스 구분하는 것도 만만한 일이 아니란 걸 알았다.
나름대로 CNN을 활용하여 Sequential 모델로 만들어봤지만 쉽사리 정확도가 높아지지 않았다는 기억이 났다.
그 때 데이터량의 부족, 학습이 안되는 현상, 과적합 현상 등 어려움이 많았다.
나중에 이미지 분류에 미리 학습된 모델들을 활용한 전이학습이 있다는 것을 보고 적용해 보니 손쉽게 정확도가 높아지는 것을 보았다.

  • 데이터 전처리
    • 이미지 crop 하고 resize, RGB 3 channel로 보정
  • mobilenetv2 사용
    • 뒤에 Dense1개, Softmax1개 사용

Test 데이터셋으로 accuracy가 70% 정도??

  • 나중에 알고보니 image color를 rescale하지 않았었다. 수정 완료. rescale=1/255로 color값을 [0,1] 범위로 함.

Try2 ; 80%

  • ImageAugumentation 으로 학습 데이터 확장. 좌우반전. 사이즈. 뒤틀림 등.
    mobilenetv2에 Dense 2개, Softmax1개 사용
    정확도 80%로 향상됨.

Try3.v1 ; 80%

training set의 정확도가 99%가 넘는데, validation은 80%였다.

  • Cross Validation?
    훈련 데이터셋 부족으로 데이터셋 재분배하여 test set, validation set으로 나누어 이어서 학습.
    training , validation set 모두 90% 이상 나옴. 그러나 학습이 계속되면 train은 99% val은 79정도로 떨어짐. test set은 80%로 여전함.
  • OOM이 자주 발생해서 고생함. batch_size 줄임. 네트웍 사이즈 줄임. 더 이상 필요없는 변수들 삭제.

Try4.v2 ; 81%

이미지의 일부를 지워서 학습??
Image part Random Remove ; resnet에 있다는 모듈을 적용시도.
ImageAugment ; shift 추가.
성능이 약간 좋아졌으나 별차이 없는 정도. 이론상 좋은 듯 한데.
lb acc 81%

Try5.v3 ; More Deep ; 83%

  • xception

원래는 Resnext50을 사용하고 싶었으나, keras 버전이 오래된 거라서 그런지 지원이 안된다.

  • 학습전이 모델 변경. mobilenetv2에서 xception으로. 파라미터수가 5배는 차이난다. 400만개 vs 2천2백만개.
  • 처음부터 다시 학습. 시간이 오래 걸림.
  • 모델은 처음부터 freezing하지 않고, 어느 정도 학습 한 후에 전이 모델만 freezing한다. 처음부터 freezing하니 정확도가 잘 안올라갔다. freezing을 풀고 학습하니 빠르게 상승하였다. 20~30에폭만에 train 80%, val 70%가 나온다. 어떤 경우는 전이모델의 상단 일부만 freezing하기도 한다.
  • train 93%, val 82% 정도까지 나옴.
  • 위 모델 2개를 만들고 병합하니 lb 83% 정도 나옴.
  • 더 학습 시킬 필요가 있어서 모델3을 생성 중. EarlyStopping 조건을 변경하여 더 오래학습되도록 patience를 증가. delta는 더 작게.

Try6. v3 ; metrics ; 91.5%

EarlyStopping 조건이 중요하다. f1_score를 조건으로 주고, 이어서 학습하되. 전이모델은 weight freezing시켰음.

  • 평균 80에폭정도 학습.
  • train 97%, val 85% 정도 나옴.
  • 데이터셋 구간을 달리하여 (cross validation) 모델 3개를 생성.
  • 개별 최대는 lb 86.8% 로 올라감.
  • 세 모델을 앙상블했더니 무려 5%나 상승하여 LB 91.58%. 드디어 90대 진입.
  • 그런데 개별로도 그 정도 나와야 되지 않나?

Try7.v4 ; 92.7%

개선해야 될 점.

  • 모델 세 개를 하나씩 불러 예측하려니 시간이 많이 소요됨. 웨이트만 저장하여 불러쓰는 것으로 하자. (이렇게 해봤는데 속도 차이가 거의 없음???)
  • weight는 best_only로 checkpoint를 저장하는 방식 사용. (monitor에 val_f1_score, mode는 max로 지정해야 함)
  • 3개를 만들어 앙상블 ; 92% (LB)

Try8. v5 ; 93.5%

  • 5개의 fold로 데이터 구분하여 새로 학습하고 5개를 앙상블해 보자.

More or Stop?

  • 일단, 현재까지 버전 commit.
  • 좀 더 올릴 수 없을까?
  • 이미지 전처리에서 crop할 때 margin을 추가할까?
  • 이미지 일부 제거 기능을 끄는 것이 좋을까?
  • 일괄 처리로 모델 5개 생성해서 다시 시도?
  • 전이학습 모델을 다른 것으로 변경해 볼까?

Try v6

  • 이미지 crop시 마진 20픽셀 추가. 이미지 왜곡시에 덜 잘릴 듯.
  • 이미지 일부 삭제 기능(cut-out)은 off 시키니까 acc 2% 감소.
  • 이미지 일부 삭제 기능이 있는 것이 좋다!

Try v7

  • 이미지 일부 삭제 on ; 반드시 사용해야 겠다.
  • 마진도 사용하는 것이 좋을 것 같다.

Try v8

  • xception과 resnet50 모델을 각각 5개씩 만들고 val_f1_score가 높은 순서대로 5개를 골라서 합의.
  • 합의 방식 ; 기존 : np.sum(a,b, axis=0)
  • 최대,최소를 버리고 중간 판정자 점수 합계??? 테스트 필요.
    • minv = np.min(…), maxv = np.max(…), np.sum() - (minv+maxv)
  • xception이 가장 괜찮은 것 같다. resnet50은 느리고 학습이 잘 안됨. mobilenetv2는 되긴 하지만 성능이 좀 떨어진다. efficientnetb2도 학습이 잘 안됨.
  • xception만으로 구성하는 것이 가장 낫다는 결론.
  • xception 모델 5개를 앙상블하면 개별로는 f1_score가 85,86,87 정도인데, 합치면 92 정도로 올라간다. (5%정도 인상)
  • Pseudo Labeling??? xception 모델에서 성능이 가장 좋은 것을 선정하여 test셋을 예측하였고, 예측시 가장 높은 확률의 클래스의 확률값을 히스토그램으로 보니, 0.99 이상이 반 정도 나왔다. 0.99 이상으로 예측한 라벨을 맞다고 가정하여, test 셋에서 라벨을 할 수 있는 부분들을 추출하여 pseudo set을 만들었다.
  • train set에 pseudo set을 추가하여 학습할 데이터를 뻥튀기하여 학습!
  • xception 모델에서 성능이 가장 좋은 것을 선정하지 않고, 앙상블하여 판단한 결과를 사용하였다. (더 확률이 올라감)
  • 90% 이상 정도는 맞출 것이고, 그 중 상위 50% 정도를 추가 학습데이터로 한 것이-라 어느 정도 일리가 있다.
  • 이렇게 훈련셋을 증가하고 기존 개별 모델들은 연속 학습하니, 개별 모델들의 f1 score가 더 올라갔다. 대략 85,86,87에서 94,95,96 정도로.(10%인상?) 이것을 다시 앙상블 한다면?
  • 결론은… 92. TT
  • 마지막에 1epoch만 all set을 대상으로 학습. 약간의 보정???
    -stratifiedkfold 적용. fold 나눌 때 클래스 비율을 유지해준다고 한다.

Try9

  • 이미지 크기 확장. 왜 224x224로 했지?(처음했던 mobilenetv2 기준). 299x299로 확장.(xception기준). 아무래도 이미지가 커야 더 잘 구분하겠다.
  • xception 베이스 모델 사용. : 기존 유지
  • cut out image (일부 손실. 자름. 검은 박스 노이즈 추가) : 기존 유지
  • 마진 20픽셀 유지하고 resize.
  • straitifiedkfold 적용. fold5으로 모델 3개 생성
  • pseudo label 삭제.
  • 진행. 먼저 single model의 성능부터 파악하자. 앙상블은 나중에.
  • 기존은 개별이 85정도 val f1 score 였다.
  • 메모리 사용량 증가로 batch는 16으로 낮춤. 나중에는 4로 낮춤.
  • Augument parameter!
    • rotation_range=20, width_shift_range=0.2, height_shift_range=0.2, horizontal_flip=True, vertical_flip=False, shear_range=0.5, brightness_range=[0.5, 1.5], fill_mode=‘nearest’, preprocessing_function=get_random_eraser(v_l=0, v_h=255)
    • 현재 진행 중인 것은 rotation은 15. 나머지는 0.1. brightness 추가. 이하 상동.
  • 메모리 부족… OOM. 메모리 부족 관련하여 좀 더 분석해야 할 것 같다.
    • 가공한 이미지를 numpy로 저장하여 불러서 다시 나누어 사용했는데, 이게 메모리 부족을 야기시키는 것 같다. 아예 처음부터 가공된 이미지를 디렉터리별 저장하고 kfold시 index로(파일명)으로 폴드에 맞는 이미지들만 로딩하여 사용하는 것이 좋은 것 같다.
    • 전체를 다 로딩하여 나누지 말고, Generator에서 디렉터리 지정하고, from dataframe으로 필요한 파일명 목록을 주는 방식으로 로딩.
    • 미처 다 못해보고 컴피티션이 종료됨.
    • 개발 환경이 좀 아쉽다. 캐글 커널로 좀 더 컴팩트하게 테스트할 수 있도록 준비가 필요할 것 같다.
    • 랜덤 고정 필요. 계속 변경되면 기준이 없어서 모델의 평가가 어렵다.

After… 94.1%

  • 다른 Pretraining Model 적용 비교
  • 이미지 전처리 결과를 numpy로 하지 않고, 이미지 파일로 저장하여 데이터셋 생성 및 로딩 방식으로 함.
  • flow_from_dataframe을 사용.
  • 이미지 크기를 299에서 250으로 줄였더니 메모리 압박에서 벗어났다.
  • Dropout 추가 : 개별로 최고 90%도 찍는다. (val_f1_score) 대략 89,90정도가 나옴.
  • Fold를 6개로 늘림.
  • 6개 네트웍 앙상블 결과 93.9%대가 나옴.
  • TTA 추가 ; 단순하게 좌우 flip만 하였다. 0.2%상승하여 94.1%대가 나옴. (최종적으로 12개의 결과를 합쳐서 평균으로 판단한 결과)

못해본 것 들…
다른 기본 네트웍 사용.
gray scale image 로 학습하는 것은 어떨까?
contour image 로 학습하는 것은 어떨까?

kaggle command

download kaggle api token (account menu)
copy to ~/.kaggle from ~/downloaddir/kaggle.json
chmod 600 ~/.kaggle/kaggle.json

kaggle competitions list -s titanic
kaggle competitions download titanic
데이터 파일 다운로드

kaggle kernels list --user junheeshin
kaggle kernels pull junheeshin/titanic-analyze
커널 소스 파일 가져옴.

Authors: crazyj7@gmail.com

'AI(DeepLearning)' 카테고리의 다른 글

[ChatGPT] 글쓰기 테스트  (1) 2023.02.09
XGBoost 요약  (0) 2019.12.06
Custom EarlyStopping  (0) 2019.11.11
타이타닉 kaggle 자료 분석  (0) 2019.08.23
Jupyter Lab/ TensorBoard 원격접속/방화벽  (1) 2019.08.09
반응형
CustomEarlyStop

Custom EarlyStopping

EarlyStop 클래스는 학습을 조기 종료시킬 때 사용한다. 학습을 무조건 많이 시킨다고 성능이 좋아지는 것은 아니다. 오히려 과적합이 발생하여 실제 테스트 데이터에 적용시 성능이 떨어질 수 있다.
따라서 어느정도가 적합한지를 자동으로 측정하는 역할을 한다.

EarlyStopping

keras.callbacks.EarlyStopping(monitor='val_loss', min_delta=0, patience=0, 
verbose=0, mode='auto', baseline=None, restore_best_weights=False)

Arguments

  • monitor : 모니터링 대상. loss, val_loss, score, val_score, val_f1_score 등 메트릭 정보를 입력한다.
  • min_delta : 최소 감지 변화량을 의미한다. 이 값보다 적은 변화는 변화(개선)가 없다고 인식한다.
  • patience : 인내할 횟수. monitor 값의 변화 감지가 개선되는 쪽으로 patience 횟수만큼 연속으로 없을 경우, 학습을 Stop하게 된다. 예를 들어 loss가 1.0이었는데, 10번 연속으로 1.0 이하로 떨어지지 않으면 학습을 중지한다. (patience=10일때) 성능은 매 epoch마다 항상 좋아지지 않고 약간 들쭉날쭉하면서 좋아지는 경향들이 있다. 이 값이 너무 커지면 학습을 너무 오래할 수 있고, 너무 작으면 너무 일찍 학습이 종료될 수 있다.
    따라서 Checkpoint와 함께 사용하여 best 상태를 항상 기록하도록 설정하는 것이 좋다.
  • baseline : monitor 값이 도달할 기본값. baseline을 넘어 개선이 이루어 지지 않으면 학습을 중지한다. (이 파라미터는 잘 안쓴다.)
  • restore_best_weights: monitor 값의 최상치일때의 weights들로 복원한다.

Custom EarlyStopping

위 EarlyStopping을 좀 수정하여 처음 100 에폭은 무조건 학습하고, 100에폭이 넘으면 그 때부터 EarlyStopping을 사용하고 싶을 때 아래와 같이 만들 수 있다.
(StackOverflow 참고)

class CustomStopper(keras.callbacks.EarlyStopping):
    def __init__(self, monitor='val_loss',
                 min_delta=0, patience=0, verbose=0, 
                 mode='auto', start_epoch = 100): # add argument for starting epoch
                super(CustomStopper, self).__init__()
                self.start_epoch = start_epoch
                
    def on_epoch_end(self, epoch, logs=None):
            if epoch > self.start_epoch:
                    super().on_epoch_end(epoch, logs)

Author: crazyj7@gmail.com

반응형
crazyj7 kaggle EDA start

Kaggle EDA Start

데이터 분석 / 그래프 작성 / 통계 정보 등

Author: crazyj7@gmail.com

In [1]:
# 경고 무시 (쓸데없는 로그 출력금지)
import warnings
warnings.filterwarnings('ignore')

import numpy as np
import pandas as pd

# 그래프 관련 
import matplotlib.pyplot as plt
import seaborn as sns
In [2]:
# plot 환경설정 기본값과 달라진 점
class DictDiffer(object):
    """
    Calculate the difference between two dictionaries as:
    (1) items added
    (2) items removed
    (3) keys same in both but changed values
    (4) keys same in both and unchanged values
    """
    def __init__(self, current_dict, past_dict):
        self.current_dict, self.past_dict = current_dict, past_dict
        self.set_current, self.set_past = set(current_dict.keys()), set(past_dict.keys())
        self.intersect = self.set_current.intersection(self.set_past)
    def added(self):
        return self.set_current - self.intersect 
    def removed(self):
        return self.set_past - self.intersect 
    def changed(self):
        return set(o for o in self.intersect if self.past_dict[o] != self.current_dict[o])
    def unchanged(self):
        return set(o for o in self.intersect if self.past_dict[o] == self.current_dict[o])
In [3]:
# make default graph configure
# 그래프 설정값을 디폴트로 리셋해 준다. 
# (가끔 앞의 그래프 설정 변경으로 잘 나오던 그래프가 이상하게 나올때 사용)
def pltconfig_default():
    sns.reset_defaults()
    %matplotlib inline
    
pltconfig_default()
In [4]:
def pltconfig_check():
    d=DictDiffer(plt.rcParams, plt.rcParamsDefault)
    for it in d.changed():
        print(it, plt.rcParamsDefault[it], plt.rcParams[it])
        
pltconfig_check()
figure.edgecolor white (1, 1, 1, 0)
figure.dpi 100.0 72.0
figure.figsize [6.4, 4.8] [6.0, 4.0]
figure.facecolor white (1, 1, 1, 0)
interactive False True
figure.subplot.bottom 0.11 0.125

load data

In [5]:
inputdir='./'
outputdir='./'

df_train = pd.read_csv(inputdir+'train.csv')
df_test = pd.read_csv(inputdir+'test.csv')

데이터 탐색

head(n), describe(), info(), columns, index
value_counts()

data explore

In [6]:
# 데이터의 일부를 관찰. (파라미터가 없으면 디폴트로 5개)
df_train.head(3)
Out[6]:
PassengerId Survived Pclass Name Sex Age SibSp Parch Ticket Fare Cabin Embarked
0 1 0 3 Braund, Mr. Owen Harris male 22.0 1 0 A/5 21171 7.2500 NaN S
1 2 1 1 Cumings, Mrs. John Bradley (Florence Briggs Th... female 38.0 1 0 PC 17599 71.2833 C85 C
2 3 1 3 Heikkinen, Miss. Laina female 26.0 0 0 STON/O2. 3101282 7.9250 NaN S
In [7]:
# 데이터의 분포를 간략히 요약. 
# 개수, 평균, 표준편차, 사분위수(최소, 최대) 등.
df_train.describe()
# 개수를 보면 어느 필드에 빠진 데이터들이 있는지 알 수 있음.
Out[7]:
PassengerId Survived Pclass Age SibSp Parch Fare
count 891.000000 891.000000 891.000000 714.000000 891.000000 891.000000 891.000000
mean 446.000000 0.383838 2.308642 29.699118 0.523008 0.381594 32.204208
std 257.353842 0.486592 0.836071 14.526497 1.102743 0.806057 49.693429
min 1.000000 0.000000 1.000000 0.420000 0.000000 0.000000 0.000000
25% 223.500000 0.000000 2.000000 20.125000 0.000000 0.000000 7.910400
50% 446.000000 0.000000 3.000000 28.000000 0.000000 0.000000 14.454200
75% 668.500000 1.000000 3.000000 38.000000 1.000000 0.000000 31.000000
max 891.000000 1.000000 3.000000 80.000000 8.000000 6.000000 512.329200
In [8]:
# info는 필드들의 정보. 데이터타입. 개수 등
df_train.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 891 entries, 0 to 890
Data columns (total 12 columns):
PassengerId    891 non-null int64
Survived       891 non-null int64
Pclass         891 non-null int64
Name           891 non-null object
Sex            891 non-null object
Age            714 non-null float64
SibSp          891 non-null int64
Parch          891 non-null int64
Ticket         891 non-null object
Fare           891 non-null float64
Cabin          204 non-null object
Embarked       889 non-null object
dtypes: float64(2), int64(5), object(5)
memory usage: 83.7+ KB
In [9]:
df_test.head()
Out[9]:
PassengerId Pclass Name Sex Age SibSp Parch Ticket Fare Cabin Embarked
0 892 3 Kelly, Mr. James male 34.5 0 0 330911 7.8292 NaN Q
1 893 3 Wilkes, Mrs. James (Ellen Needs) female 47.0 1 0 363272 7.0000 NaN S
2 894 2 Myles, Mr. Thomas Francis male 62.0 0 0 240276 9.6875 NaN Q
3 895 3 Wirz, Mr. Albert male 27.0 0 0 315154 8.6625 NaN S
4 896 3 Hirvonen, Mrs. Alexander (Helga E Lindqvist) female 22.0 1 1 3101298 12.2875 NaN S

NULL (Missing) 데이터 검사

In [10]:
df_train.isnull().sum()
Out[10]:
PassengerId      0
Survived         0
Pclass           0
Name             0
Sex              0
Age            177
SibSp            0
Parch            0
Ticket           0
Fare             0
Cabin          687
Embarked         2
dtype: int64
In [11]:
# 데이터 분포도
# 히스토그램으로 구간별 카운팅
# 박스플롯으로 어느 지점에 데이터가 밀집해 있는지 알 수 있다. 
fig, axs = plt.subplots(1,2)
df_train.Fare.plot.hist(ax=axs[0])
df_train.boxplot(['Fare', 'Age', 'SibSp', 'Parch'], ax=axs[1])  # 파라미터 지정이 없으면,  주어진 dataframe의 모든 컬럼별 데이터 분포
Out[11]:
<matplotlib.axes._subplots.AxesSubplot at 0x7f29002a30b8>
In [12]:
# 평균 , 표준편차
print('fare mean=', df_train.Fare.mean(), df_train.Fare.std())
# 표준 편차는 정규분포를 따를때,  평균에서 +- 1 표준편차는 전체의 65% 정도가 해당되고,
# # +-2표준편차는 95%, +-3표준편차는 99%정도로 본다. (1.96이 95%, 2.58이 99%)
# 사분위수
print('quantile = ', df_train.Fare.quantile(0), df_train.Fare.quantile(0.25), df_train.Fare.quantile(0.5), df_train.Fare.quantile(0.75), 
                  df_train.Fare.quantile(0.99), df_train.Fare.quantile(1))
fare mean= 32.204207968574636 49.6934285971809
quantile =  0.0 7.9104 14.4542 31.0 249.00622000000033 512.3292

데이터 수정/병합

In [13]:
# df3 = pd.concat([df1 , df2], axis=0)  
# df3 = df1.append(df2, ignore_index=True)  
# df4.drop(columns='age', inplace=True)  

df_train.head()
print(df_train.shape)
(891, 12)
In [14]:
df_test.head()
df_test.shape
Out[14]:
(418, 11)
In [15]:
# train, test 데이터가 survived를 제외하고 동일함. 합쳐서 전처리 작업을 할 수 도 있다.
# drop은 columns or rows를 삭제할 수 있다. (array로 여러개 지정 가능)
# concat은 병합. axis로 방향. 다른 방법으로는 df_train.append(df_test)을 리턴으로 받으면 된다.
# iloc는 array index로 filtering
# inplace는 자체 수정 여부. (False이면 자체수정없이 수정된것을 반환.)
# ignore_index=True 옵션을 주면, 인덱스를 0부터 새로 매긴다. False이면 인덱스 값이 중복되더라도 유지한다.

# df_all = pd.concat([df_train.iloc[:,2:], df_test.iloc[:,1:]], axis=0)
# or
df_all = pd.concat([df_train.drop(columns='Survived'), df_test], axis=0)
In [16]:
# passengerid는 의미없으므로 제거.
df_all.drop(columns='PassengerId', inplace=True)
In [17]:
df_all.head()
Out[17]:
Pclass Name Sex Age SibSp Parch Ticket Fare Cabin Embarked
0 3 Braund, Mr. Owen Harris male 22.0 1 0 A/5 21171 7.2500 NaN S
1 1 Cumings, Mrs. John Bradley (Florence Briggs Th... female 38.0 1 0 PC 17599 71.2833 C85 C
2 3 Heikkinen, Miss. Laina female 26.0 0 0 STON/O2. 3101282 7.9250 NaN S
3 1 Futrelle, Mrs. Jacques Heath (Lily May Peel) female 35.0 1 0 113803 53.1000 C123 S
4 3 Allen, Mr. William Henry male 35.0 0 0 373450 8.0500 NaN S
In [18]:
# 컬럼 타입별로 구분. 숫자와 숫자 아닌 것. 위에 info()에 마지막에 dtypes 참고.
df_num = df_all.select_dtypes(include=['int64', 'float64'])
df_str = df_all.select_dtypes(include=['object'])

df_num.describe()
Out[18]:
Pclass Age SibSp Parch Fare
count 1309.000000 1046.000000 1309.000000 1309.000000 1308.000000
mean 2.294882 29.881138 0.498854 0.385027 33.295479
std 0.837836 14.413493 1.041658 0.865560 51.758668
min 1.000000 0.170000 0.000000 0.000000 0.000000
25% 2.000000 21.000000 0.000000 0.000000 7.895800
50% 3.000000 28.000000 0.000000 0.000000 14.454200
75% 3.000000 39.000000 1.000000 0.000000 31.275000
max 3.000000 80.000000 8.000000 9.000000 512.329200
In [19]:
# 스트링 컬럼으로 보면, 클래스 개수(unique참조), 전체 개수 파악(미싱제외)
df_str.describe()
Out[19]:
Name Sex Ticket Cabin Embarked
count 1309 1309 1309 295 1307
unique 1307 2 929 186 3
top Kelly, Mr. James male CA. 2343 C23 C25 C27 S
freq 2 843 11 6 914
In [20]:
# 필드값별로 카운팅
df_train['Survived'].value_counts()
Out[20]:
0    549
1    342
Name: Survived, dtype: int64
In [21]:
# ## 스트링 필드를 분할하여 추가 컬럼들을 만들기

lstPath = ['img100_GENUINE.jpg', 'img101_FRAUD.jpg', 'img102_GENUINE.jpg', 'img103_FRAUD.jpg', 'img104_FRAUD.jpg', 'img105_GENUINE.jpg']
dfSample = pd.DataFrame({'path':lstPath})
dfSample
Out[21]:
path
0 img100_GENUINE.jpg
1 img101_FRAUD.jpg
2 img102_GENUINE.jpg
3 img103_FRAUD.jpg
4 img104_FRAUD.jpg
5 img105_GENUINE.jpg
In [22]:
# expand를 True로 하면 n개의 컬럼으로 리턴.
# expand를 False로 하면 1개의 컬럼내에 list로 리턴.
dfSplit = dfSample['path'].str.split('_', expand=False)
print(dfSplit[0][0], dfSplit[0][1])
print(dfSplit[1][0], dfSplit[1][1])
img100 GENUINE.jpg
img101 FRAUD.jpg
In [23]:
dfSplit = dfSample['path'].str.split('_', expand=True)

dfSample['name'] = dfSplit[0]
dfSample['tf'] = dfSplit[1].str.replace('.jpg', '')

dfSample
Out[23]:
path name tf
0 img100_GENUINE.jpg img100 GENUINE
1 img101_FRAUD.jpg img101 FRAUD
2 img102_GENUINE.jpg img102 GENUINE
3 img103_FRAUD.jpg img103 FRAUD
4 img104_FRAUD.jpg img104 FRAUD
5 img105_GENUINE.jpg img105 GENUINE

Submission 데이터만들기

In [24]:
df_submit = pd.read_csv(inputdir+'gender_submission.csv')
print(df_submit.head())
print(df_submit.columns)
   PassengerId  Survived
0          892         0
1          893         1
2          894         0
3          895         0
4          896         1
Index(['PassengerId', 'Survived'], dtype='object')
In [25]:
# 필드값 바꿔서 제출하기
# df_submit.describe()
print('record count=', df_submit.shape[0])
dfsubmit2 = df_submit.copy()
# 원하는 필드값을 변경한다.
dfsubmit2['Survived'] = np.zeros(df_submit.shape[0], dtype=int)
print(dfsubmit2.head())
# dfsubmit2.to_csv('result.csv')
record count= 418
   PassengerId  Survived
0          892         0
1          893         0
2          894         0
3          895         0
4          896         0
In [26]:
# 샘플을 참고하지 않고 직접 만들어 제출하기
pids = df_submit['PassengerId'].values
surv = df_submit['Survived'].values
print(pids.shape)
print(surv.shape)
(418,)
(418,)
In [27]:
dfresult = pd.DataFrame({'PassengerId':pids, 'Survived':surv})
print('columns=', dfresult.columns)
print('index=', dfresult.index)
print(dfresult.head())
columns= Index(['PassengerId', 'Survived'], dtype='object')
index= RangeIndex(start=0, stop=418, step=1)
   PassengerId  Survived
0          892         0
1          893         1
2          894         0
3          895         0
4          896         1
In [28]:
# 경우에 따라 인덱스를 특정 필드로 지정해줘야 되는 서미션도 있음. 제출형식을 확인해야 함.
dfresult.set_index('PassengerId', inplace=True)
print('columns=', dfresult.columns)
print('index=', dfresult.index)
print(dfresult.head())
columns= Index(['Survived'], dtype='object')
index= Int64Index([ 892,  893,  894,  895,  896,  897,  898,  899,  900,  901,
            ...
            1300, 1301, 1302, 1303, 1304, 1305, 1306, 1307, 1308, 1309],
           dtype='int64', name='PassengerId', length=418)
             Survived
PassengerId          
892                 0
893                 1
894                 0
895                 0
896                 1

matplotlib plot

matplotlib 그래프 좌표축의값 없애기

plt.axis('off')
 axarr[uid].axis('off')
 axarr[uid].set_xticks(p[])
 plt.xticks([])

박스 제거

 ax1 = plt.axes(frameon=False)   # remove box
 or
 ax1 = plt.axes() ;
 ax1.set_frame_on(False)

y축 뒤집기

plt.gca().invert_yaxis()
 # or
 ax=plt.gca()
 ax.set_ylim(ax.get_lim()[::-1])

그래프간 간격 조정

plt.subplots_adjust(hspace=0.5, wspace=0.4)

가로/세로 비율 유지(좌표값을 절대적 기준)

ax.set_aspect('equal', 'box')

직선 그리기 (by 기울기)

def abline(slope, intercept):
     axes = plt.gca()
     x_vals = np.array( axes.get_xlim())
     y_vals = intercept+slope*x_vals
     plt.plot(x_vals, y_vals, 'r--')

plot 파라미터/함수

     lw : 선 두께
     c : 색깔
     s : 사이즈
     alpha : 투명도 (0일 수록 투명. 1일수록 불투명)
     label : legend 출력시 표시
     marker : 표시도형 o, x 등 
     'r--' : 빨간 점선
     'g^' : green 세모
     'ro' : 빨간 o
     'bs' : 파란 네모

     plt.title()
     plt.xlabel()
     plt.ylabel()
     plt.xlim(0,10) : x 범위
     plt.ylim(20,30) : y 범위
     plt.grid() : 눈금 표시
     plt.plot() : 꺽은선 그래프. 좌표들을 연결. lw, c, alpha, label
     plt.scatter() : 산점도 그래프. 좌표에 점(마커)를 찍는다. marker, c, alpha, label, s
     plt.legend() : 비고 박스, edgecolor='r' 로 박스라인 색깔지정 가능

     plt.tight_layout() : 여백없앰
     plt.scatter(x,y, linewidth=1, marker='o', facecolors='none', edgecolors='r')  : 빈 원 그리기
     plt.axhline(y, color='r') : 가로선
     plt.axvline(x, color='b') : 세로선

plot 저장

 plt.figure()
 plt.plot...
 plt.savefig('aaa.png') # 파일로 저장. 화면 출력여부는 아래코드
 plt.show() # 이것을 생략하면 화면 출력 안됨.
 plt.close()

ax 함수

ax.set_title()
 ax.set_xlabel()
 ax.set_ylabel()
 ax.set_xlim()
 ax.set_ylim()

개수 분포 그래프

  • dataframe.value_counts().plot.bar() / plot.pie()
  • sns.countplot()
In [29]:
# scatter 그래프

plt.figure()
# plt.grid('on')
plt.title('age and fare')
flagman=df_train['Sex']=='male'
plt.scatter( df_train.loc[flagman]['Age'], df_train.loc[flagman]['Fare'], c='blue', alpha=0.3, label='male')
flagfemale = ~flagman
plt.scatter( df_train.loc[flagfemale]['Age'], df_train.loc[flagfemale]['Fare'], marker='x', c='red', alpha=0.3, label='female')
plt.axhline(y=200)
plt.xlabel('Age')
plt.ylabel('Fare')
plt.legend(edgecolor='red')  # 비고박스(legend) 외곽라인 색 지정 가능 
plt.show()
plt.close()
In [30]:
# plot . x 라벨 지정 및  회전 
x = [1, 2, 3, 4]
y = [1, 4, 9, 6]
labels = ['Frogs', 'Hogs', 'Bogs', 'Slogs']
plt.plot(x, y)
# You can specify a rotation for the tick labels in degrees or with keywords.
plt.xticks(x, labels, rotation='vertical')
# Pad margins so that markers don't get clipped by the axes
plt.margins(0.2)
# Tweak spacing to prevent clipping of tick-labels
plt.subplots_adjust(bottom=0.15)
plt.show()
plt.close()
In [31]:
# 개수 분포, 그래프
df_train['Survived'].value_counts().plot.bar()
Out[31]:
<matplotlib.axes._subplots.AxesSubplot at 0x7f28ffba2160>
In [32]:
# 카테고리 분포 
df_train['Embarked'].value_counts().plot.pie(autopct='%.2f %%')
plt.legend()
Out[32]:
<matplotlib.legend.Legend at 0x7f28ffb96e80>
In [33]:
# 카테고리 분포. 그룹별. stack bar
dfembarkedsurv = df_train.groupby(['Embarked', 'Survived'])['Survived'].count().unstack('Survived').fillna(0)
dfembarkedsurv.plot(kind='bar', stacked=True)
Out[33]:
<matplotlib.axes._subplots.AxesSubplot at 0x7f28ffafc9b0>
In [34]:
# 여러 그래프를 한 번에 그리기.
# 두 가지 방법이 있다.
# plt.subplots 와 plt.subplot 
#  subplots는 리턴받아 사용. subplot은 리턴값 안받고 그때그때 사용.
# 
# ex) subplot(행,열, 현재번호)
# plt.subplot(1,2,1)
# plot...
# plt.subplot(1,2,2)
# plot...
# ex) f,ax = subplots(행,열)
# plots... by ax[인덱스번호]
# 
# 생존자 비율
# plt.figure()
f, ax = plt.subplots(1,2)

df_train['Survived'].value_counts().plot.pie(explode=[0, 0.1], autopct='%.2f%%', ax=ax[0], shadow=True)
ax[0].set_title('Survived ratio')
ax[0].set_ylabel('')

# Survived 컬럼 카운트 (dataframe plot보다 이쁨)
sns.countplot('Survived', data=df_train, ax=ax[1])
Out[34]:
<matplotlib.axes._subplots.AxesSubplot at 0x7f28ffa24b38>
In [35]:
# 위와 같은 그림을 다른 방식으로
plt.figure(figsize=(2*5,5))
plt.suptitle('Bit Title', fontsize='x-large')

plt.subplot(1,2,1)
plt.title('title1')
xs = df_train['Survived'].value_counts()
print(xs.values)
df_train['Survived'].value_counts().plot.pie(autopct='%.2f %%', labels=['Dead', 'Survived'])  #autopct='%.2f %%'

plt.subplot(1,2,2)
plt.title('title2')
sns.countplot('Survived', data=df_train)

plt.show()
[549 342]
In [36]:
# 가로축에 값이 많은 경우, 글씨가 안보임. 글씨 회전
import random
# 랜덤 스트링 분포도
rs=[]
rs2=[]
for i in range(1000):
    c = chr(np.random.randint(0, 26)+ord('A'))  # 주의! random.randint(0,26) 이 아니다. np.random.randint와 사용방식이 다름!
    rs.append(c)
    c = chr(random.randint(0, 25)+ord('A'))  # random.randint는 마지막값이 범위에 포함된다!!! 
    rs2.append(c)
# print(rs)
# print(rs2)

from collections import Counter

# +
counter1 = Counter(rs)
dfc1 = pd.DataFrame([ [x1,x2] for x1,x2 in counter1.items() ], columns=['Letter', 'Count'])
dfc1 = dfc1.sort_values('Count', ascending=False)

plt.figure()
# sns.barplot(dfc1['Letter'], dfc1['Count'], color='blue', label='LetterCount')
sns.barplot(dfc1['Letter'], dfc1['Count'], label='LetterCount') # 색상이 없으면 무지개색 
plt.show()
In [37]:
# x 축을 일치시키고 y값 비교하기 / x축 회전 rotation

dfc1 = dfc1.sort_values('Letter', ascending=True)

counter2 = Counter(rs2)
dfc2 = pd.DataFrame([ [x1,x2] for x1,x2 in counter2.items() ], columns=['Letter', 'Count'])
dfc2 = dfc2.sort_values('Letter', ascending=True)
xvalue = dfc1['Letter']

plt.figure(figsize=(8, 6))
plt.title('Letter Count')
plt.xticks(rotation=90)   # x 라벨 회전. (글자가 겹칠때 유용함)
sns.barplot(xvalue, dfc1['Count'], color='blue', alpha=0.5, label='by np')
sns.barplot(xvalue, dfc2['Count'], color='red', alpha=0.5, label='by random')
plt.legend()
plt.show()
    
# -

그룹별 카운팅

  • dataframe.groupby() : array로 여러개 가능
  • sns.countplot() : hue
  • dataframe.crosstab() : 표생성. 세로필드, 가로필드. (세로필드를 array로 어러개 가능)
  • sns.factorplot(x,y,hue) : y평균값 그래프. hue로 지정된 필드의 종류만큼 라인이 그려짐.
  • sns.violinplot(x,y,hue) : y값의 범위와 분포를 알 수 있는 그래프.
In [38]:
# 성별과 생존 관계
df_train.groupby(['Sex', 'Survived'])['Survived'].count()
Out[38]:
Sex     Survived
female  0            81
        1           233
male    0           468
        1           109
Name: Survived, dtype: int64
In [39]:
sns.countplot('Sex', hue='Survived', data=df_train)
Out[39]:
<matplotlib.axes._subplots.AxesSubplot at 0x7f28ff7fa278>
In [40]:
sns.countplot('Embarked', hue='Sex', data=df_train)
Out[40]:
<matplotlib.axes._subplots.AxesSubplot at 0x7f28ff78f898>
In [41]:
pltconfig_check()
figure.edgecolor white (1, 1, 1, 0)
figure.dpi 100.0 72.0
figure.figsize [6.4, 4.8] [6.0, 4.0]
figure.facecolor white (1, 1, 1, 0)
interactive False True
figure.subplot.bottom 0.11 0.125
In [42]:
# 두 개의 기준으로 groupby한 카운팅
pd.crosstab(df_train['Sex'], df_train['Survived'], margins=True).style.background_gradient(cmap='summer_r')
Out[42]:
Survived 0 1 All
Sex
female 81 233 314
male 468 109 577
All 549 342 891
In [43]:
## 피클래스와 생존 관계
pd.crosstab(df_train['Pclass'], df_train['Survived'], margins=True).style.background_gradient(cmap='summer_r')
Out[43]:
Survived 0 1 All
Pclass
1 80 136 216
2 97 87 184
3 372 119 491
All 549 342 891
In [44]:
sns.countplot('Pclass', hue='Survived', data=df_train)
Out[44]:
<matplotlib.axes._subplots.AxesSubplot at 0x7f28ff1d3828>
In [45]:
## 성별과 피클래스에 따른 생존
In [46]:
pd.crosstab([df_train.Sex, df_train.Pclass], df_train.Survived, margins=True).style.background_gradient(cmap='summer_r')
Out[46]:
Survived 0 1 All
Sex Pclass
female 1 3 91 94
2 6 70 76
3 72 72 144
male 1 77 45 122
2 91 17 108
3 300 47 347
All 549 342 891
In [47]:
pd.crosstab([df_train.Sex, df_train.Survived], df_train.Pclass, margins=True).style.background_gradient(cmap='summer_r')
Out[47]:
Pclass 1 2 3 All
Sex Survived
female 0 3 6 72 81
1 91 70 72 233
male 0 77 91 300 468
1 45 17 47 109
All 216 184 491 891
In [48]:
## 평균 꺽은선 그래프
In [49]:
sns.factorplot('Pclass', 'Survived', hue='Sex', data=df_train)
Out[49]:
<seaborn.axisgrid.FacetGrid at 0x7f28ff75a278>
In [50]:
sns.factorplot('Pclass', 'Age', hue='Sex', data=df_train)
Out[50]:
<seaborn.axisgrid.FacetGrid at 0x7f2935cdef60>
In [51]:
sns.violinplot('Pclass', 'Age', hue='Survived', data=df_train, split=True)
Out[51]:
<matplotlib.axes._subplots.AxesSubplot at 0x7f2934c07a90>
In [52]:
pltconfig_check()
figure.edgecolor white (1, 1, 1, 0)
figure.dpi 100.0 72.0
figure.figsize [6.4, 4.8] [6.0, 4.0]
figure.facecolor white (1, 1, 1, 0)
interactive False True
figure.subplot.bottom 0.11 0.125

히스토그램

  • dataframe.plot.hist(bins=count, color='blue')
  • sns.FaceGrid(data, hue), map, plt.hist : hue를 주면 hue로 지정된 필드의 종류별로 겹침.
In [53]:
# +
# df_train['Age'].value_counts()

# +
# 히스토그램. 두 개 비교.

# 연령대별 생존자 수, 사망자 수 2개 그래프 겹침 
grid = sns.FacetGrid(df_train, hue='Survived', size=4)
# bins는 개수로 지정할 수 도 있지만, 구간을 입력할 수도 있다.
grid.map(plt.hist, 'Age', alpha=.6, rwidth=0.8, bins=[0,10,20,30,40,50,60,70,80,90,100])
# bins 구간에 맞추어 x tick을 지정해 준다.
xlist=list(range(0, 110, 10))
print(xlist)
plt.xticks(xlist)
grid.add_legend()
[0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100]
Out[53]:
<seaborn.axisgrid.FacetGrid at 0x7f2934ba26d8>
In [54]:
# 위 히스토그램을 각각 그리기
grid = sns.FacetGrid(df_train, col='Survived', size=4, margin_titles=True)
grid.map(plt.hist, 'Age', bins=[0,10,20,30,40,50,60,70,80,90,100], color='green', histtype='step') # histtype 생략시(default='bar') 색칠한 일반 모양
# title을 value로 지정
# grid.set_titles(row_template='{row_name}', col_template='{col_name}')  # 이것을 생략하면 제목은 알아서 column=value가 된다. 
Out[54]:
<seaborn.axisgrid.FacetGrid at 0x7f28ffcd70b8>
In [55]:
# 히스토그램. 
df_train[ df_train['Survived']==0 ].Age.plot.hist(bins=20, color='red', rwidth=0.9)  
# rwidth (0~1)범위로 가로크기 비율을 정해 여백을 줄 수 있다.
xlist = list(range(0, 85, 5))
plt.xticks(xlist)
plt.margins(x=0)  # 안쪽 x 마진 제거
plt.show()
In [56]:
# FacetGrid로 가로로 여러 그래프 그리기(그룹/컬럼별)
grid = sns.FacetGrid(df_train, col='Embarked', size = 3)
grid.map(sns.barplot, 'Sex', 'Survived', palette='deep', order=['female','male'])  
# order가 없으면 male, female 순으로 나온다. 
Out[56]:
<seaborn.axisgrid.FacetGrid at 0x7f28ff811cf8>

상관계수

In [57]:
# Dataframe 상관계수 테이블 correlation 
df_num.corr()
Out[57]:
Pclass Age SibSp Parch Fare
Pclass 1.000000 -0.408106 0.060832 0.018322 -0.558629
Age -0.408106 1.000000 -0.243699 -0.150917 0.178740
SibSp 0.060832 -0.243699 1.000000 0.373587 0.160238
Parch 0.018322 -0.150917 0.373587 1.000000 0.221539
Fare -0.558629 0.178740 0.160238 0.221539 1.000000
In [58]:
# 상관계수 히트맵 
sns.heatmap( df_train.drop('PassengerId', axis=1).corr(), annot=True)
Out[58]:
<matplotlib.axes._subplots.AxesSubplot at 0x7f28ff880ac8>
In [59]:
cols = ['Survived', 'SibSp', 'Parch', 'Fare']
cm = np.corrcoef(df_train[cols].values.T)
sns.set(font_scale=1.25)
hm = sns.heatmap(cm, cbar=True, annot=True, square=True, 
  fmt='.2f', annot_kws={'size':10} , yticklabels=cols, xticklabels=cols)
In [60]:
# 컬럼별 2차원 데이터 분포도. scatter, histogram.
sns.set()
cols=['Age', 'Survived', 'Fare']
sns.pairplot(df_train[cols], size=2.5)
plt.show()

pltconfig_check()
grid.color #b0b0b0 white
patch.force_edgecolor False True
lines.solid_capstyle projecting round
ytick.color black .15
xtick.minor.width 0.6 1.0
patch.edgecolor black w
font.size 10.0 12.0
xtick.labelsize medium 11.0
ytick.major.size 3.5 6.0
axes.titlesize large 12.0
axes.linewidth 0.8 1.25
xtick.color black .15
axes.facecolor white #EAEAF2
axes.prop_cycle cycler('color', ['#1f77b4', '#ff7f0e', '#2ca02c', '#d62728', '#9467bd', '#8c564b', '#e377c2', '#7f7f7f', '#bcbd22', '#17becf']) cycler('color', [(0.2980392156862745, 0.4470588235294118, 0.6901960784313725), (0.8666666666666667, 0.5176470588235295, 0.3215686274509804), (0.3333333333333333, 0.6588235294117647, 0.40784313725490196), (0.7686274509803922, 0.3058823529411765, 0.3215686274509804), (0.5058823529411764, 0.4470588235294118, 0.7019607843137254), (0.5764705882352941, 0.47058823529411764, 0.3764705882352941), (0.8549019607843137, 0.5450980392156862, 0.7647058823529411), (0.5490196078431373, 0.5490196078431373, 0.5490196078431373), (0.8, 0.7254901960784313, 0.4549019607843137), (0.39215686274509803, 0.7098039215686275, 0.803921568627451)])
text.color black .15
interactive False True
xtick.minor.size 2.0 4.0
ytick.major.width 0.8 1.25
xtick.bottom True False
ytick.minor.width 0.6 1.0
figure.edgecolor white (1, 1, 1, 0)
figure.dpi 100.0 72.0
axes.labelsize medium 12.0
figure.figsize [6.4, 4.8] [6.0, 4.0]
axes.axisbelow line True
grid.linewidth 0.8 1.0
font.sans-serif ['DejaVu Sans', 'Bitstream Vera Sans', 'Computer Modern Sans Serif', 'Lucida Grande', 'Verdana', 'Geneva', 'Lucid', 'Arial', 'Helvetica', 'Avant Garde', 'sans-serif'] ['Arial', 'DejaVu Sans', 'Liberation Sans', 'Bitstream Vera Sans', 'sans-serif']
legend.fontsize medium 11.0
figure.subplot.bottom 0.11 0.125
xtick.major.width 0.8 1.25
axes.edgecolor black white
ytick.labelsize medium 11.0
axes.grid False True
patch.facecolor C0 (0.2980392156862745, 0.4470588235294118, 0.6901960784313725)
ytick.minor.size 2.0 4.0
axes.labelcolor black .15
ytick.left True False
xtick.major.size 3.5 6.0
image.cmap viridis rocket

Evaluation

In [61]:
#  confusion_matrix( real, predict ) : real vs predict 결과 비교. 대각선이 많을수록 맞춘것임.

from sklearn.metrics import confusion_matrix

y_real=[]
y_predict=[]
for i in range(1000):
    v = np.random.randint(0, 10)
    y_real.append(v)
    if np.random.rand()<0.8:
        y_predict.append( np.random.randint(0, 10))
    else:
        y_predict.append(v)
cm = confusion_matrix(y_real, y_predict)  # row=real, column=predict
cm
Out[61]:
array([[21,  8,  7,  8,  9,  7,  7,  7,  6,  7],
       [12, 15,  4,  9,  6, 10, 10, 12,  6,  2],
       [ 7, 10, 33,  5, 10,  8,  8,  6,  9,  8],
       [ 9, 13,  7, 27,  9,  8,  9,  6, 14, 10],
       [ 6, 10, 10,  7, 41, 13, 12,  6,  8,  8],
       [ 6,  9,  9,  7,  3, 29,  9,  8, 14,  5],
       [14,  7,  6, 11,  7, 12, 23, 10,  7,  7],
       [15, 10, 11,  8,  7,  4,  6, 22,  4,  6],
       [ 9,  5,  8,  6,  5,  9,  4,  8, 34, 11],
       [ 6,  8,  4,  6,  9,  7, 12,  8,  4, 31]])
In [62]:
# draw confusion matrix with seaborn
df_cm = pd.DataFrame(cm, index=range(10),
                  columns=range(10))
# plt.figure(figsize = (10,7))
# sns.set(font_scale=1.4)  # for label size. 변경시 다른 plot도 전부 영향을 받음.
sns.heatmap(df_cm, annot=True,annot_kws={"size": 10})  # font size
# sns.set(font_scale=1.0) # back to the default font size.... 
# 설정 변경시 이후 다른 plot 환경 변화로 문제가 발생.
Out[62]:
<matplotlib.axes._subplots.AxesSubplot at 0x7f29349d73c8>
In [63]:
pltconfig_check()
grid.color #b0b0b0 white
patch.force_edgecolor False True
lines.solid_capstyle projecting round
ytick.color black .15
xtick.minor.width 0.6 1.0
patch.edgecolor black w
font.size 10.0 12.0
xtick.labelsize medium 11.0
ytick.major.size 3.5 6.0
axes.titlesize large 12.0
axes.linewidth 0.8 1.25
xtick.color black .15
axes.facecolor white #EAEAF2
axes.prop_cycle cycler('color', ['#1f77b4', '#ff7f0e', '#2ca02c', '#d62728', '#9467bd', '#8c564b', '#e377c2', '#7f7f7f', '#bcbd22', '#17becf']) cycler('color', [(0.2980392156862745, 0.4470588235294118, 0.6901960784313725), (0.8666666666666667, 0.5176470588235295, 0.3215686274509804), (0.3333333333333333, 0.6588235294117647, 0.40784313725490196), (0.7686274509803922, 0.3058823529411765, 0.3215686274509804), (0.5058823529411764, 0.4470588235294118, 0.7019607843137254), (0.5764705882352941, 0.47058823529411764, 0.3764705882352941), (0.8549019607843137, 0.5450980392156862, 0.7647058823529411), (0.5490196078431373, 0.5490196078431373, 0.5490196078431373), (0.8, 0.7254901960784313, 0.4549019607843137), (0.39215686274509803, 0.7098039215686275, 0.803921568627451)])
text.color black .15
interactive False True
xtick.minor.size 2.0 4.0
ytick.major.width 0.8 1.25
xtick.bottom True False
ytick.minor.width 0.6 1.0
figure.edgecolor white (1, 1, 1, 0)
figure.dpi 100.0 72.0
axes.labelsize medium 12.0
figure.figsize [6.4, 4.8] [6.0, 4.0]
axes.axisbelow line True
grid.linewidth 0.8 1.0
font.sans-serif ['DejaVu Sans', 'Bitstream Vera Sans', 'Computer Modern Sans Serif', 'Lucida Grande', 'Verdana', 'Geneva', 'Lucid', 'Arial', 'Helvetica', 'Avant Garde', 'sans-serif'] ['Arial', 'DejaVu Sans', 'Liberation Sans', 'Bitstream Vera Sans', 'sans-serif']
legend.fontsize medium 11.0
figure.subplot.bottom 0.11 0.125
xtick.major.width 0.8 1.25
axes.edgecolor black white
ytick.labelsize medium 11.0
axes.grid False True
patch.facecolor C0 (0.2980392156862745, 0.4470588235294118, 0.6901960784313725)
ytick.minor.size 2.0 4.0
axes.labelcolor black .15
ytick.left True False
xtick.major.size 3.5 6.0
image.cmap viridis rocket
In [64]:
pltconfig_default()
pltconfig_check()
figure.edgecolor white (1, 1, 1, 0)
figure.dpi 100.0 72.0
figure.figsize [6.4, 4.8] [6.0, 4.0]
figure.facecolor white (1, 1, 1, 0)
interactive False True
figure.subplot.bottom 0.11 0.125
In [65]:
import itertools

def plot_confusion_matrix(cm, classes,
                          normalize=False,
                          title='Confusion matrix',
                          cmap=plt.cm.Blues):
    """
    This function prints and plots the confusion matrix.
    Normalization can be applied by setting `normalize=True`.
    """
    plt.figure()
    plt.grid('off')
    plt.imshow(cm, interpolation='nearest', cmap=cmap)
    plt.title(title)
    plt.colorbar()
    tick_marks = np.arange(len(classes))
    plt.xticks(tick_marks, classes, rotation=45)
    plt.yticks(tick_marks, classes)

    if normalize:
        cm = cm.astype('float') / cm.sum(axis=1)[:, np.newaxis]

    thresh = cm.max() / 2.
    for i, j in itertools.product(range(cm.shape[0]), range(cm.shape[1])):
        plt.text(j, i, cm[i, j],
                 horizontalalignment="center", verticalalignment="center",
                 color="white" if cm[i, j] > thresh else "black")

    plt.tight_layout()
    plt.ylabel('True label')
    plt.xlabel('Predicted label')
In [66]:
plot_confusion_matrix(cm, classes=range(10))
plt.show()
plt.close()
In [67]:
pltconfig_check()
figure.edgecolor white (1, 1, 1, 0)
figure.dpi 100.0 72.0
figure.figsize [6.4, 4.8] [6.0, 4.0]
figure.facecolor white (1, 1, 1, 0)
interactive False True
figure.subplot.bottom 0.11 0.125
In [ ]:
 
In [ ]:
 
반응형
TensorBoardRemote

Jupyter Lab/ TensorBoard remote monitoring through firewall

서버 방화벽으로 6006포트가 막힌 원격 PC에서 서버의 텐서보드를 모니터링하는 방법! & 같은 방법으로 서버의 jupyter lab을 원격 PC에서 여러 개 접속하기

서버 환경에서 python 코드를 돌려 tensorboard 로그가 쌓이고 있는 상황에서 서버에서 tensorboard를 보려면 일단 텐서보드 서버를 아래와 같이 실행한다. (로그 경로 지정)

$ tensorboard --logdir="./log"

이렇게 로그 폴더만 지정해 주고, 서버의 웹 브라우저에서
http://localhost:6006 으로 접속하면 된다.

그리고 해당 서버의 6006 포트가 방화벽으로 막혀 있지 않다면 원격 PC에서 위 http 주소에 localhost대신 서버 ip를 지정해주면 볼 수 있다.

만약 방화벽으로 막혀있으면 당연 접속이 안될 것인데, 우회하는 방법이 있다.

원리는 바로 ssh로 port forwarding을 이용하는 것이다. (당연히 서버에 ssh 포트는 방화벽으로 열려있어야 한다.)

위와 같은 조건에서 PC에 16006 포트를 만들고 이 포트와 서버의 6006 포트를 ssh로 연결한다.

PC에서 서버로 ssh 접속을 다음과 같이 한다. (윈도우면 cmd창을 띄우고 작업)

 ssh -L 16006:localhost:6006 [ID]@[ServerIP]

서버의 ssh 포트번호가 22가 아니면 -p [port] 를 추가한다.
ssh 접속이 완료되면, PC에서 브라우저를 띄우고 아래 주소로 접속
http://localhost:16006
이미지 001

Jupyter Lab Remote Connect

Jupyter Lab이나 Jupyter Notebook도 마찬가지로 서버의 로컬에서만 접속 가능한 경우에 원격 접속을 위해 동일하게 처리할 수 있다.
먼저 안전하게 설정 파일 생성과 접속암호를 아래와 같이 만든다.

$jupyter notebook --generate-config
$jupyter notebook password
암호 입력

암호 설정 방법은 수동으로도 할 수 있다. ~/.jupyter/ 폴더 내에 생성된 설정 파일을 보면 복잡하지만 가능하다. 간단하게 하려면 위 방식을 이용하자.

서버에서 작업할 디렉터리로 이동 후, 쥬피터 랩 실행

$ jupyter lab
... http://localhost:port ...

위와 같이 포트 번호를 안내해 준다. 이미 할당되어 있으면 변경되므로 확인.
(쥬피터를 디렉터리를 달리하여 여러 개 실행할 수도 있다.)

PC에서 서버로 ssh 접속을 다음과 같이 한다. (윈도우면 cmd창을 띄우고 작업) -L 뒤에 PC포트:localhost:서버포트
서버 포트는 서버 연결포트이니 당연히 쥬피터 포트를 보고 입력해 준다.

 ssh -L 8890:localhost:8890 [ID]@[ServerIP]

PC에서 로컬호스트의 생성한 PC포트로 접속한다. (위와 같이 PC포트 서버 포트가 일치할 필요는 없다. 로컬 포트는 할당되지 않은 임의의 포트로 지정해도 된다.)
http://localhost:8890
암호를 입력하고 연결하면 된다.

jupyterlab

Written with StackEdit.

반응형

keras 손실함수 중에 아래 두 개가 비슷하지만 사용할 때는 완전히 다르다.

주의가 필요하다.


+ categorical_crossentropy ; 다중 분류 손실함수. one-hot encoding 클래스

출력값이 one-hot encoding 된 결과로 나오고 실측 결과와의 비교시에도 실측 결과는 one-hot encoding 형태로 구성된다.

예를 들면 출력 실측값이 아래와 같은 형태(one-hot encoding)로 만들어 줘야 하는 과정을 거쳐야 한다.

[[0 0 1]

[0 1 0]

[1 0 0]]  (배치 사이즈 3개인 경우)

네트웍 레이어 구성시 마지막에 Dense(3, activation='softmax') 로 3개의 클래스 각각 별로 positive 확률값이 나오게 된다.

[0.2, 0.3, 0.5]

위 네트웍 출력값과 실측값의 오차값을 계산한다.

model.compile(optimizer=.., loss='categorical_entropy')


+ sparse_categorical_crossentropy ; 다중 분류 손실함수. 위와 동일하지만 , integer type 클래스라는 것이 다르다.

예를 들면 출력 실측값이 아래와 같은 형태로 one-hot encoding 과정을 하지 않아도 된다. 

[0, 1, 2]  (배치 사이즈 3개로 했을 때)


네트웍 구성은 동일하게 Dense(3, activation='softmax')로 하고 출력값도 3개가 나오게 된다.

단 실측 출력값을 입력하는 부분에서 별도로 one-hot encoding을 할 필요가 없이 정수값 그대로 주고, 손실함수를  sparse_categorical_crossentropy 로 바꿔주기만 하면 된다.

model.compile(optimizer=.., loss='sparse_categorical_entropy')





반응형

word vector로 기사 카테고리 분류하기 level 1

가설 ; 어떤 기사에 많이 나온 주요 단어들은 카테고리 키워드와의 유사도가 다른 것 보다 높을 것이다.

이 방식의 정확도가 높지는 않겠지만 그런대로 어느 정도는 될 것으로 예상된다.

하지만 장점으로는 언제든지 카테고리를 늘리거나 줄이거나 원하는대로 변경할 수 있다.


(먼저 워드벡터 학습모델이 있어야 되는데 이 전편에 나무위키로 워드벡터 만들기를 보면 된다. )


+알고리즘


기사를 읽고, 단어 분리

단어별 카운팅. 상위 탑 10 단어 추출.

카테고리명과 상위 탑10 단어의 유사도 계산

스코어 계산 (단어의 빈도를 가중치로하여 카테고리와의 유사도 곱으로 평균을 냄)

카테고리 중 가장 높은 스코어를 선정.


스코어 계산은 카테고리와의 유사도인 단어가 많이 나올수록 높도록 측정하였음.


'''
기사 분류기
나무위키로 학습한 워드 벡터를 이용.
주제별 단어와 기사의 유사성을 측정하여 max 분류로 한다.
기사와의 유사성 측정은?
기사내의 단어(조사 등 제외) 분포를 찾아 의미 있는 것을 찾아,스코어화.
'''
import codecs
from bs4 import BeautifulSoup
from konlpy.tag import Okt
from gensim.models import word2vec
import time
import numpy as np

category = ['정치', '경제', '사회', 'IT', '과학', '자동차', '부동산',
'생활', '세계', '의학', '인테리어', '예술', '연예']

filename='namu_test_article.txt'
filename4 = './hub/namu.model'


def make_DF(filename):
file = codecs.open(filename, 'r', encoding='utf-8')
text = file.read()

twitter = Okt()
word_dic = {}
lines = text.split('\r\n')
for line in lines:
malist = twitter.pos(line)
for taeso, pumsa in malist:
if pumsa == 'Noun':
if not (taeso in word_dic):
word_dic[taeso] = 0
word_dic[taeso] += 1
print(word_dic)
keys = sorted(word_dic.items(), key=lambda x: x[1], reverse=True)

top20_dic = {}
if len(keys)>20:
for word, count in keys[:20]:
top20_dic[word]=count
else:
for word, count in keys:
top20_dic[word]=count
return top20_dic


print('Model test')
t1 = time.time()
model = word2vec.Word2Vec.load(filename4)
t2 = time.time()
print('model load elapsed=', t2-t1)
top20_dic=make_DF(filename)
for ks in top20_dic.keys():
print(ks, top20_dic[ks], end=" ,")

# 카테고리별 단어의 유사도
cascores=[]
for ca in category:
sims = []
dfs = []
for ks in top20_dic.keys():
try:
v1 = model.similarity(ca, ks)
sims.append( v1 )
except KeyError:
sims.append( 0.0 )
v2 = top20_dic[ks]
dfs.append( v2 )
print(ca, ks, 'similarity=',v1, 'df=',v2)

sims = np.asarray(sims)
dfs = np.asarray(dfs)

# 단어출연 빈도를 가중치로 한 스코어
val = np.dot(sims, dfs)
print('wsum=', val)
sco=val/ np.sum(dfs)
print('scor=', sco)
cascores.append(sco)

cascores=np.asarray(cascores)
maxidx = np.argmax(cascores)

# print(category)
# print(cascores, maxidx)

categorydic = {
cate:scor for cate, scor in zip(category, cascores)
}
pc=sorted(categorydic, key=lambda k:categorydic[k], reverse=True)
print(pc)
print( sorted(cascores, reverse=True) )
print( 'predict=',pc[0],"/",pc[1] )


이렇게 하여 테스트 결과.

Model test

model load elapsed= 21.66822624206543

{'디넷': 1, '코리아': 1, '봉삼': 1, '기자': 1, '방탄소년단': 3, '컴백': 2, '카카오': 2, '운영': 1, '음원': 1, '플랫폼': 1, '멜론': 13, '이': 1, '먹통': 1, '이용자': 3, '불편': 3, '오후': 1, '접속': 4, '문제': 2, '발생': 2, '오류': 3, '등': 2, '트래픽': 2, '번': 2, '불': 1, '안정': 1, '현상': 1, '것': 1, '추정': 1, '실행': 1, '인터넷': 2, '수': 2, '상태': 2, '확인': 1, '메시지': 1, '지속': 1, '검색': 1, '포털': 1, '실시간': 1, '급상승': 1, '검색어': 1, '단어': 1, '그': 1, '만큼': 1, '사용자': 1, '오류로': 1, '뜻': 1, '로고': 2, '팬': 1, '게시판': 1, '통해': 1, '호소': 1, '컴퓨터': 1, '겨우': 1, '몇': 1, '재생': 1, '목록': 1, '장난': 1, '말': 1, '다른': 1, '서버': 2, '위': 1, '관리': 1, '좀': 1, '측은': 1, '일시': 1, '면서': 1, '조속': 1, '정상화': 1, '고': 1}

멜론 13 ,접속 4 ,방탄소년단 3 ,이용자 3 ,불편 3 ,오류 3 ,컴백 2 ,카카오 2 ,문제 2 ,발생 2 ,등 2 ,트래픽 2 ,번 2 ,인터넷 2 ,수 2 ,상태 2 ,로고 2 ,서버 2 ,디넷 1 ,코리아 1 


  v1 = model.similarity(ca, ks)

정치 멜론 similarity= 0.10295023 df= 13

정치 접속 similarity= 0.14711404 df= 4

정치 방탄소년단 similarity= 0.14685516 df= 3

정치 이용자 similarity= 0.34247914 df= 3

정치 불편 similarity= 0.20862463 df= 3

정치 오류 similarity= 0.22307779 df= 3


... 중략....

연예 인터넷 similarity= 0.42752212 df= 2

연예 수 similarity= 0.11581904 df= 2

연예 상태 similarity= 0.17616633 df= 2

연예 로고 similarity= 0.3842223 df= 2

연예 서버 similarity= 0.114044465 df= 2

연예 디넷 similarity= 0.114044465 df= 1

연예 코리아 similarity= 0.3931188 df= 1

wsum= 14.374487452208996

scor= 0.2613543173128908

['연예', 'IT', '경제', '부동산', '사회', '정치', '예술', '과학', '세계', '자동차', '생활', '인테리어', '의학']

[0.2613543173128908, 0.24636683274399152, 0.22802816277200524, 0.22646296511996877, 0.20992791205644606, 0.2065649455243891, 0.19927997887134552, 0.18424408056519248, 0.17951921116222036, 0.17361825514923443, 0.15364200567657296, 0.14810618719255383, 0.13615213415839456]

predict= 연예 / IT

스코어 높은 순으로 카테고리를 분류하여 정렬 결과 

연예 기사로 잘 분류하였다. 

실제 여러 기사로 해 보면 종종 오탐이 발생한다. 

단순하게 카테고리명과의 단어 유사도만으로 측정해서 한계는 있다.

다음엔 좀 더 나은 방식으로 해보자.


+ Recent posts