입짧은달님 2021. 12. 16. 14:22

https://book.naver.com/bookdb/book_detail.nhn?bid=16299590 

전체적인 프로세스는 다음의 책을 참고했다.

 

XAI 설명 가능한 인공지능, 인공지능을 해부하다

XAI(EXPLAINABLE ARTIFICIAL INTELLIGENCE)는 인공지능의 판단 이유를 설명하는 연구 분야로, 인공지능 기술이 확대되면서 그 필요성이 함께 증가하고 있습니다. 이것은 알고리즘의 설계자조차 인공지능의

book.naver.com

전처리는 아래의 글을 참조했다.

https://wikidocs.net/44249

 

6) 네이버 영화 리뷰 감성 분류하기(Naver Movie Review Sentiment Analysis)

이번 챕터에서는 영어 데이터가 아닌 한국어/한글 데이터에 대해서 텍스트 분류를 수행해보겠습니다. 방법 자체는 영어 데이터에 대한 텍스트 분류와 크게 달라지지는 않았습니다. ...

wikidocs.net

 

대리 분석

인공 지능 모델이 너무 복잡해서 분석이 불가능할 때 유사한 기능을 흉내내는 인공지능 모델 여러개를 만들어서 본래 모델을 분석하는 기법.

장점: Model-agnostic: 모델에 대한 지식 없이도 학습할 수 있음

 

글로벌 대리 분석

전체 train 데이터를 이용해 (블랙박스 모델인) f 를 따라 g 를 만들고 g 를 해석 가능하도록 변조 . 이때 g는 설명 가능한 모델이어야 한다.

 

로컬 대리 분석

데이터 하나에 대해 블랙박스가 해석하는 과정을 분석하는 기법

 

LIME(Local Interpretable Model - agnostic Explanation)

:모델이 현재 데이터의 어떤 영역을 집중해서 분석했고, 어떤 영역을 분류 근거로 사용했는지 알려주는 XAI 기법

 

실습: 

백의진님(Quarter, 29.9세)이 주신 버즈 train data와 test data를 사용했다.

 

train data 와 test 데이터 

 

def true_y(self, x):
if x == 0:
return '거래판매'
elif x == 1:
return '렌탈'
elif x == 2:
return '부동산'
elif x == 3:
return '수리'
elif x == 4:
return '이벤트'
elif x == 5:
return '인사글'
elif x == 6:
return '종교'
elif x == 7:
return '주식'
else:
return '체험단'

라벨이 의미하는 것 

 

 

전처리는 최대한 간단하게 하겠다.

#한글만 남기고 제거
jytrain['document'] = jytrain['document'].str.replace("[^ㄱ-ㅎㅏ-ㅣ가-힣 ]","")
jytest['document'] = jytest['document'].str.replace("[^ㄱ-ㅎㅏ-ㅣ가-힣 ]","")

okt 로 토큰화 하고 불용어를 제거한다.

#토큰화
stopwords = ['의','가','이','은','들','는','좀','잘','걍','과','도','를','으로','자','에','와','한','하다']
#train_data에 형태소 분석기를 사용하여 토큰화를 하면서 불용어를 제거하여 X_train에 저장

okt = Okt()

X_train = []
for sentence in tqdm(jytrain['document']):
    if len(sentence.split(' '))>=100 :#속도상 100글자 이하만 쓰도록 함
        pass
    else:
        tokenized_sentence = okt.morphs(sentence, stem=True) # 토큰화
        stopwords_removed_sentence = [word for word in tokenized_sentence if not word in stopwords] # 불용어 제거
        X_train.append(stopwords_removed_sentence)

버즈의 글자수를 설명하는 describe

test data도 이렇게 해준다.

 

 

TF-IDF 를 사용해서 문서를 숫자 벡터로 변환한다.

너무힘들다..벼락치기중...

import sklearn.feature_extraction
import sklearn.metrics
from sklearn.naive_bayes import MultinomialNB

#TF-IDF를 사용해서 문서를 숫자 벡터로 변환하는 전처리 과정
vectorizer=sklearn.feature_extraction.text.TfidfVectorizer(preprocessor=' '.join,lowercase=False)
train_vectors=vectorizer.fit_transform(X_train)
test_vectors=vectorizer.transform(X_test)

#학습하기
nb=MultinomialNB(alpha=.01)
nb.fit(train_vectors,jytrain.iloc[:2220,2])

#테스트하기
pred=nb.predict(test_vectors)
sklearn.metrics.f1_score(jytest.iloc[:,2],pred,average='weighted')

0.8304224400125914

약 83%의 성능을 내는 버즈 카테고리를 분류하는 모델을 만들었다!

 

XAI 적용하기 

파이프라인 기능을 사용해보자. (가독성 높은 코드를 위해)

#파이프라인 기술을 사용해 테스트 데이터 인덱스 0번에 데이터 벡터라이저와 카테고리 분류를 한꺼번에 수행
from sklearn.pipeline import make_pipeline

pipe=make_pipeline(vectorizer,nb)
predict_classes=pipe.predict_proba([X_test[0]]).round(3)[0]
predict_classes

predict_classes
Out[15]: array([0.   , 0.861, 0.037, 0.016, 0.   , 0.025, 0.   , 0.06 , 0.   ])

 

2번째 카테고리에 속할 확률이 가장 높다.(86%)

 

이제 LIME을 사용해서 버즈 분류기 모델을 설명해 보자.

 

#LIME 텍스트 설명체를 선언하는 코드
from lime.lime_text import LimeTextExplainer

explainer=LimeTextExplainer()

0번 데이터에 LIME을 적용해 보자!

exp=explainer.explain_instance(str(X_test[0]),pipe.predict_proba,top_labels=1)
exp.available_labels()

[0]

 

거래 판매 게시물이라고 한다.. 너무 불안하다.

완전 틀림.. 근데 test set 라벨도 틀려서 안심이 된다.

exp=explainer.explain_instance(jytest['document'].iloc[44],pipe.predict_proba,top_labels=2)
exp.available_labels()

[0,7]

 

44번 글을 확인해본다.

계속 상위 주제에 0이 떠서 꼼수로 탑레벨을 2로 지정했다. 엉엉.... 

7: 주식이다.

뒷걸음질 치다 맞은 격으로 맞았다.

 

그럼 이제 Lime의 하이라이트 기능을 알아보자.

exp.save_to_file("../test44.html")

점점 쓰레기가 되어가고 있다...

 

이건 어디 보여줄 수 가 없는 수준이다...

어쨌든 처음 해본 것에 의의를 두자.ㅎㅎ

눈물이 앞을 가린다.... 어쨌든 4시간만 한거니까!(자기합리화)