-> https://docs.google.com/document/d/1yJCyF5LRKcDj6SuUizXL2T35H_P-qTxJsrI5faRKuZk/edit?usp=sharing
20193228 허지은
- 게임유저가 특정한 인물을 생각하고 게임에서 제시하는 질문에 답을 하면 게임이 유저가 어떤 인물을 생각했는지 맞추는 인물 유추 프로그램
- 정해진 질문 내에서 사용자에게 질문을 제공해야한다.
- 어떤 질문을 했을 때 분류가 더 잘 되는지에 따라 질문이 제공 돼야 한다.
- 사용자의 답변은 버튼으로 입력받아 다른 값이 입력되는 경우를 제거한다.
- 사용자의 질문에 따라 결과를 도출하고 사용자에게 결과값을 보여준다.
- 사용자가 답변을 선택하면 다음 질문으로 넘어가야한다.
- 데이터를 입력받는 경우 사용자가 입력한 사람의 이름이 옳은 값인지 확인한다.
- 새로운 데이터를 입력받을 때는 주어진 모든 질문에 답을 하게 한다.
- yes, no button으로 잘못된 데이터가 입력될 경우를 제거한다
- 데이터를 저장하는 화면과 게임을 진행하는 화면을 분리한다.
- 기본적으로 학습에 필요한 데이터를 위해 게임진행 부분과 데이터 수집 부분으로 UI를 만들예정
- 그냥 인물로 설정하면 인물유추의 범위가 방대하여 한정된 인물 안에서만 유추하도록 함.
- 질문을 설정하고 해당 질문에 대한 답변으로 인물 유츄
- 특정 질문을 정해서 정해진 질문에 답하여 데이터를 추가
-
특정 인물 : 모니카, 허니제이, 리헤이, 가비, 아이키, 노제 , 효진초이, 리정
-
질문 : '파워풀한 안무를 좋아한다.', ‘위트있고 센스있는 안무가 좋다.', ‘좋은 리더보다는 팀을 위한 리더이다.', '힙합을 좋아한다.', '빨간색이 생각난다.', ‘꿈을 이루기 위해서라면 뭐든 할 것 같다.', ‘이름이 본명과 관련되어 있다.', 'k-pop 안무를 많이 만든 댄서다.', 'YG와 관련있다.', '춤을 가르치는 교수님이다.', '평소 진한 화장을 좋아하는 댄서다.', '스우파 전부터 원래 유명한 댄서이다.', '별명이 "아기고양이" 이다.'
- Decision tree로 구현하는 방법
- 배열로 입력받아 같은 배열 찾아내는 방법
- decision tree는 특정데이터로 학습을 시키고 새로운 데이터를 분류할 때 많이 사용하는데 질문을 사용자에게 하나씩 입력받으면서 분류를 진행하려면 어떻게 해야 할까?
- 질문을 선정하는 함수와 선택 결과에 따라 데이터 split하는 함수, gini impurity와 정보이득을 계산하는 함수를 구현해야함
- sklearn을 사용하면 바로 분류가 가능하지만 그러면 중간 중간에 사용자에게 질문을 받아 결과를 도출 할 수 없다. 그리고 꼭 모든 질문에 답변을 해야한다.
- 만약 똑같은 데이터를 가진 배열이 없다면 새로운 데이터로 저장을 하던지 해야함. 아니면 추측실패 오류 메세지를 출력
- 기존데이터와 동일한 데이터를 찾기위해서는 모든 질문에 답변을 해야함.
- 같은 배열을 가진 사람이 여러명이라면 어떻게 할 것인가?
- 랜덤으로 한명을 뽑아야 하나?
- 질문이 9개 이면 yes/no 2가지로 답변할 대 경우의 수가 2^9으로 512개인데 이 경우의 수를 모두 반영 할 수 있나?
- 데이터를 받았을 때 똑같은 데이터를 찾기 위해서 모든 경우의 수를 가지고 있어야하는 문제가 생김
- 만약 모든 경우의 수를 다 만들었다 해도 같은 데이터를 가진 다른 사람이 있을 수 도 있는데 그럼 이런 경우는 어떻게 해야 하나?
-> 기존 데이터와 같은 데이터를 찾아내는 방법으로 logic을 구현하기에는 너무 많은 무리가 있음. decision tree로 구현하고 사용자의 질문에 따라 tree를 만들어가는 방향으로 logic구현.
- start Button : 게임을 진행하는 화면으로 전환
- data 저장 button : 데이터를 저장하는 화면으로 전환
-
질문 보여주는 widget : logic에 의해 선정된 적절한 질문들을 하나씩 보여주는 창
-
답변 button : 질문에 따라 yes/no로 답변할 수 있는 버튼
-
홈 button :이전 화면인 home으로 돌아가는 button
-
메시지 출력 widget : 데이터의 결과값이 나오면 ‘당신이 생각한 사람은 바로’ 라는 메세지를 출력한다.
-
추측한 인물 보여주는 widget : 데이터의 결과값을 보여준다.
-
홈 버튼 : 이전 화면인 home으로 돌아가는 button
msg 창 : 정해진 인물들 중 한명의 이름을 입력하라는 msg출력 답변 입력 창 : 사용자가 정한 인물의 이름을 입력하는 곳 질문보여주는 창 : 미리 정해진 질문을 순서대로 출력 답변 button : 질문에 따라 해당 인물에 대해 yes/no로 답변하는 button 홈 button : 이전 화면이 홈 화면으로 돌아가는 button
- gini impurity를 계산해야한다.
- 정해진 질문 중 어느 질문이 변별력이 있는지 판단
- gini impurity가 낮을수록 좋은 질문
- 만약 gini impurity가 같은 질문이 있으니 가중치를 줘서 계산을 한다.
- information gain을 계산해서 물어볼 질문을 선정
- 분할 전 gini impurity와 분할 후 gini impurity의 차를 계산
- information gain도 같은 값이 나올 수 있으니 가중치 줘서 더 좋은 질문 선정
- 질문이 선택되면 답변에 따라 data가 나뉘어야 한다.
- 나뉜 data중에서 변별력이 제일 좋은 질문 다시 설정한다.
- 결과가 나올 때 까지 계속 위의 과정 반복
- 반복문을 써야 하나 재귀함수를 써야하나?
- 반복문을 쓸경우 overfiting 될 가능성이 커짐
- 재귀함수로 구현시 탈출 조건은 뭐가 되야 하는가?
- dataframe을 어떻게 관리할 것인가?
- 질문과 질문에 대한 답변, 답변에 대한 결과값, 인물의 이름을 어떻게 관리할 것인지.
- 불러온 data를 어떻게 필터링 할것인지
- 질문에 관한 데이터, 답변에 관한 데이터, 결과값을 담은데이터, 사람이름을 담은 데이터로 나누어서 데이터 관리
- 답변에 관한 데이터와 결과값을 담은 데이터는 새로운 데이터가 추가 됨으로 텍스트 파일로 관리하기로 한다.
- 질문과 사람이름은 정해져있는 데이터로 사용자에게 추가받을 일이 없음으로 배열로 관리하기로 한다.
- 답변에 대한 데이터는 질문에 대한 답이 yes이면 1, no 이면 0으로 저장
- 결과값을 담은 데이터는 사람이름을 담은 배열에 저장된 index값으로 결과값 저장
ex ) 종류 : 사과, 귤, 포도 질문 : 빨간색인가?, 주황색인가?, 보라색인가?
-
질문에 관한 배열 [ ‘빨간색인가?’, ‘ 주황색인가?’, ‘보라색인가?’]
-
종류를(사람이름을) 담은 배열 [‘사과’, ‘귤’, ‘포도’]
-답변에 관한 데이터 1, 0, 0 0, 1, 0 0, 0, 1
- 결과값을 담은 데이터 0 1 2
- decision tree logic 구현상세 설계
5.1 계산해야 하는 변수들
- impurity = 1 - (각 그룹에 속한 데이터의 각 label이 차지하는 비율의 제곱)
- weighted(가중치) = 분할 후 데이터 수 / 분할 전 데이터 수
- weighted impurity = 분할 후 데이터 수 / 분할 전 데이터 수 * impurity
- weighted information gain = 분할 적 impurity - 분할 후 weight impurity 들
- 모든 질문을 기준으로 yes/no 답변에 따라 weighted information gain을 계산 해서 가장 information gain이 놓게 계산된 질문을 선정한다. 사용자에게 입력을 받아 yes/no답변에 따라 데이터를 분류한 후 다시 위의 과정을 반복한다.
- 반복의 종료조건 : information gain을 얻을 수 있는 질문이 더 이상 존재 하지 않거나 information gain의 값이 0이면 종료
- 특정 데이터 set이 주어졌을 때 해당데이터 셋의 gini impurity를 계산하고 이를 반환하는 함수
- 파라미터 : dataset / data가 들어있는 배열
- 시작 impurity는 1로 설정
- 각 class들이 차지하는 비율의 제곱값을 impurity에서 빼나간다.
-특정 데이터셋의 분할 전과 후의 impurity를 계산 후 분할 전 impurity에서 분할 후 impurity값을 뺀 imformation_gain값을 return
- 파라미터 : 분열전 data ( privious_data), 분열 후 data(split_data)
- return값 : info_gain -처음에 분열 전 data의 weight impurity값을 저장, split_data의 weight impurity값을 뺌.
-
사용자가 답한 것을 기준으로 데이터셋을 분할하고 분할 된 데이터 그룹과 각 그룹이 포함하는 class를 반환하는 함수
-
파라미터 : 분류할 data(data), 질문들(questions), 기준으로 사용할 질문(feat_ques)
-
data_subsets = [] : 분할 후의 데이터 그룹을 저장하는 배열
-
label_subset = [] : 분할 후의 질문 그룹을 저장하는 배열
-
counts : 주어진 기준 질문에 unique한 값들을 저장
-
반복문을 사용하여 user_answer의 답과 feat_ques의 답이 같은 data만 data_subset에 append, data_subsets에 append하는 data의 종류를 label_subset에 추가
-
return 값: data_subset, label_subset
- 특정 질문을 기준으로 데이터셋을 분할하고 분할된 데이터 그룹과 각 그룹이 포함하는 class를 반환하는 함수
- 파라미터 : 분류할 data(data), 질문들 (questions), 기준으로 사용할 질문(feat_ques)
- data_subset = [] :분할 후의 데이터 그룹을 저장하는 배열
- label_subset = [] :분할 후의 질문 그룹을 저장하는 배열
- counts :주어진 기준 질문에 unique한 값들을 저장
- for문
- new_data_subsets : 특정 값 K를 기준으로 분할 된 그룹에 속한 데이터를 저장하는 배열
- new_label_subset :특정 값 K를 기준으로 분할 된 그룹에 포함되는 결과값들을 저장하는 배열
- for문
- dataset의 data갯수만큼 반복
- dataset의 data에서 해당 질문의 답과 특정 값 k가 같으면 data를 new_data_subset에 저장. 해당 label을 new_label_subest에 저장
- new_data / label_subset을 data/label_subset에 추가
- return 값 : data_subset, label_subset
- split함수에 전달할 최적의 feature 질문을 찾는다.
- 파라미터 : 데이터(dataset), 질문들(question)
- 초기값 best_gain = 0 : 데이터를 특정 featur로 분할 했을 때 가장 높게 측정된 information_gain
- best_feature = 0 :데이터를 분할 할 질문의 idx저장
- return 값 : best_feature, best_gain
- find_best_split으로 데이터를 분할 할 최적의 feature을 찾는다.
- 만약 분할 후의 information gain이 0이라면 해당 노드는 더 분할 할 필요가 없으므로 information gain이 0이라면 해당 노드는 더 분할 할 필요가 없으므로 반복 종료
- 찾은 best_feature을 질문으로 출력 -user_answerss : 사용자의 질문에 대한 답을 저장 -> 굳이 모든 answer들을 저장해야 하나?
- 입력받은 답으로 split함수 (data, label, best_feature, user_answer)호출
- return 값 : split해서 얻은 data_subset과 label_subsets
startWindow : 게임 시작부분 window gui를 구현한 class initUI : 시작 window에서 필요한 gui layout을 구현 openGameWindw : start버튼을 눌렀을 때 gameWindow가 실행할 수 있도록 연결, gameWidow를 종료했을 때 다시 startWindo 돌아오게 함. openDataWIndow : data버튼을 눌렀을 때 dataWIndow가 실행할 수 있도록 연결, dataWidow를 종료했을 때 다시 startWindo 돌아오게 함.
GameWIndow : 게임이 진행되는 window gui를 구현한 class. initUI : game window에서 필요한 gui layout을 구현. startGame : 게임을 시작할 때 필요한 초기값을 설정. printQuestion : 선택된 질문을 text창에 출력하여 사용자에게 보여줌. delUserAnswer : 사용자가 button을 통해 입력한 답변을 처리하고 guess함수를 호출해 다음 질문이 진행되게 함 . guess : 처음 사용자가 게임을 시작하면 바로 질문을 출력하고 information gain의 값이 0인지 아닌지 판단해 반복의 종료를 판단. gain이 0이면 결과값 출력. home : start Window로 돌아가고 해당 window는 hide. DataWindow : data를 저장할 때 window gui를 구현한 class initUI : data window에서 필요한 gui layout을 구현. nextQuestion : 사용자가 질문에 답변을 하면 다음 답변을 출력 만약 질문이 마지막이면 데이터 값을 저장하고 startWindow로 나감. dealUserAnswer : 사용자의 답변이 yes이면 1, no이면 0으로 해서 값을 저장. addData : 사용자에게 입력받은 데이터를 guessData file에 저장, 결과값은 guessResult file에 저장 home : startWindow로 돌아가고 해당 window는 hide showMessageBox : 값이 잘못 입력된 경우 사용자에게 메세지를 보냄.
decisionTreeOperation : decision tree를 구현하는데 필요한 동작들을 모아놓은 class gini: gini impurity를 계산. -information_gain : 정보이득 계산. split : 사용자의 답변에 맞추어 data를 분류. bestSplit : 최적의 질문을 찾기위해 gini를 계산 할 때 호줄되는 split. findBestSplit : 모든 질문의 정보 이득을 계산해서 최적의 질문을 찾는 함수.
dataFile : data file로 저장되어 있는 dataset과 result값을 배열로 바꾸는 함수




