공부 겸.. 업무 겸(?)...

  • 전화 시스템에 대해서 알아야 할 필요가 있기도 했고, 궁금하기도 했다.
  • 온라인에서 이것저것을 찾아서 볼 수 있지만... 참... 온라인 자료는 정리가 잘 되어 있지 않다.
  • 그러다 한 블로그를 찾았는데 ( https://www.nexpert.net/715 ) 글이 잘 정리 되어 있었다.
  • 마침 책이 나왔다는 글까지 봐서 책을 구매.
  • 가격은 좀 비싼 편(2.8만원)이다. 부크크( http://www.bookk.co.kr/ ) 라는 플랫폼을 이용하는데, 자가 출판 플랫폼이다.
  • 그러니.. 좀 비쌀 수 밖에... 하지만 책 쓴 사람에게 많이 돌아 간다면 이해 할 수 있다. ( 회사 돈이기도 했고 ㅎ )

책 읽기 전

  • 이 책에서는 전화망에 관련되는 정보가 있다.
  • 그 중에서도 SIP 관련 내용이 대부분이나, "전화망 그 자체"에 대한 정보도 많기 때문에, 전화망에 대해서 궁금하다면 읽으면 괜찮을거라 생각한다.
  • 다만, 원래 관심이 있었던 IP-PBX 에 대한 내용은 단어 정도만 나오긴 하지만...
  • 그래도, 많은 도움이 되었다.

책 정리

  • 이 책의 주요 내용을 모두 요약하는건 너무 어렵다. 특히 SIP 프로토콜 부분은 RFC 문서를 설명하고 있는거라서...
  • 그러므로, 전화망에 대한 몇가지 지식이나, 용어들에 대해서만 정리 하도록 하겠다.

정리

주요 용어

  • IDF : Intermediate Distribution Frame, 중간 단자함. 각층에 전화선이 모여 있는 곳. 아파트에서는 각층의 계단실 같은곳에 있다.

  • MDF : Main Distribution Frame. 주 배선반. 국선 단자함. 건물의 지하나 1층에 모든 전화선이 모이는곳.

  • PBX : Private Branch Exchange, 사설 전화를 처리하는 장비. 내선은 외부로 나가지 않고, PBX에서 내선끼리 연결된다. 작은것은 전화 2개 정도만 처리하는것도 있고, 많은것은 100개 가까이 처리하는것도 있는듯 하다.

  • PSTN : Public Switched Telephone Network. 일반 전화망. 전화선이 모인 PBX 끼리 연결된 전화망이라고 생각하면 된다.

  • DTMF : Dual Tone Multiple Frequency. 전화 번호를 누르면 나오는 "띠 띠" 소리가, 2가지 이상의 톤을 같이 소리를 내는것이다. 이 정보를 이용해서 전화 번호를 전달한다.

  • FXO : 전화기 포트 중, 전화국에서 오는쪽의 포트. 즉 벽에 설치 되어 있는 포트를 FXO 라고 부른다.

  • FXS : 전화기 포트 중, 전화기에 연결되는 쪽의 포트. 즉 전화가에 연결되는 포트를 FXS 라고 부른다.

  • IP-BPX : Internet Protocol Private Branch Exchange. PBX와 동일하지만, 전화선이 아니라, 인터넷을 이용해서 전화를 할 수 있도록 하는 장비

  • VoIP : Voice over Internet Protocol. 인터넷을 이용하는 전화. 일반적으로는 인터넷을 이용해서 전화를 걸고 이를 PSTN(일반전화선)으로 전화를 받거나, 그 반대의 경우에 대해서 이야기 한다. 아날로그 음성을 디지털 패킷으로, 디지털 패킷을 아날로그 음성으로 변환해야 하는데, VoIP GateWay가 이 역할을 한다.

  • SIP : 일반전화선이 아니라, 인터넷을 이용해서 전화를 할 수 있는 프로토콜. 인터넷을 이용해서 전화를 할 수 있는 몇가지 프로토콜이 있긴한데, 현재는 다들 SIP를 쓰고 있음.

  • 아.. 귀찮으니깐 나머지는 생략... ㅎㅎ.

허허 참.... 또 뜬다..

  • 근데 좀 다른 점을 발견해서 기록으로...
  • 테스트 주소 : http://woollimcoop.org/?m=bbs&bid=contact
  • 재현 방법 : 위 주소에 접속 한 뒤, F5를 빠른 시간에 여러번 누른다.

문제 추측 1 : 팝업을 허용한 곳이 있어서 생기는 문제 아닐까?

  • 웹브라우져를 사용하다보면 팝업을 허용하게 되는곳이 한 두 곳 생긴다.
  • 팝업을 허용한 A 사이트가 있고, B 사이트에서는 팝업이 막혀 있을때, B 사이트에서 A 사이트의 url을 iframe 등으로 loading 한 뒤, popup을 띄우면 가능하지 않을까? 라는 생각이 들었다.
  • 그래서 팝업이 허용되어있는 모든 사이트를 삭제 했지만, 팝업이 뚫고 나오는 문제 발생
  • 재현 동영상
  •  

문제 추측 2 : 익스텐션(확장) 문제가 아닐까?

  • 설치된 익스텐션 중 일부의 기능이나, 버그를 우회해서 팝업을 띄우는게 아닐까 생각을 해 보았다.
  • 그래서 모든 익스텐션을 disable 시키고 테스트 해 보았으나, 실패...
  • 그래서 팝업 블로커 익스텐션만 따로 설치해서 테스트 해도, 팝업이 뚫고 나오는 문제 발생
  • 재현 동영상
  •  

그래서..

  • 걍 이쯤에서 포기하고 크롬을 새로 깔까 생각중...;;;
  1. June 2019.08.08 09:30

    모비온 회사에서 아래 링크와 같이 차단하는 방법을 안내하고 있는데요,
    이 방법으로 차단이 되는 건지 한번 봐주시면 좋겠어요
    http://www.mediacategory.com/mediaCategory/ad/mobon_user_policy_linfo.html

    • 2019.08.12 23:41 신고

      안녕하세요 ^_^
      해당 내용은 "맞춤 광고"에 대한 내용입니다.

      "맞춤 광고"라는건 사용자의 사용 기록을 확인하여, 그에 맞는 광고를 보여주는 것입니다.

      팝업이 뜨는것과를 별개로 보입니다. ^_^

  2. Ann 2019.12.11 00:54

    안녕하세요, 3탄까지 보고 많이 참고했었는데 4탄을 이제야 봣네요... 저는 관련 문제에 접근해야 했는데 팝업이 안떠서 고민이었습니다. ㅠㅠ

    개인적으로 팝업이 뜨는 이유를 확인해 보면 '시점' 문제인 것 같습니다. 연속적으로 클릭이 발생하게 되는데 이게 대부분의 경우에는 막히지만 간혹가다가 브라우저서 block이 발동하기 전에 뚫고 나오는 놈들이 있는 것 같은.... 허허

    해당 유입 분석을 해보면 크롬 말고도 삼성 인터넷, 사파리(잡힙니다. 왠지는 모르겠으나), 안드로이드 기타 웹뷰, 익플 등등 다양하게 적용되고 있었습니다. ㅜ

    • 2019.12.11 12:36 신고

      답변 감사드립니다. ^_^ 저 역시 그렇게 생각하고 있습니다.

      재미난건... 저도 요즘에는 팝업이 안 뜨고 있습니다. ㅎㅎ ;; 제가 별 달리 한 일이 없는것 같은데 말이죠. ㅎㅎ.

      답글 달아 주셔서 감사합니다. ^_^

오늘 또.. 광고가...

  • 광고 팝업 관련해서 댓글을 달아 주신 내용을 참고삼아 #_enliple 을 검색해 보았더니.. 세상에. 링크의 끝에 #_enliple 이 붙어 있는게 너무 많더라...

어떻게 저 링크가 만들어 질까?

  • 궁금해서 링크가 있는것들을 찾아서 소스코드를 확인해 보니 자주 보였던 mobon.net 이 보인다. 그리고 dreamsearch.or.kr 도 보인다.
  • mobon.net에서 사용되는 javascript는 아래와 같다.
    • 코드를 간단히 설명하면,
      • 해당 사이트에 접근해서 url에 #_enplie라는 hash가 없으면, url 주소의 끝에 #_enplie를 붙여 주고
      • hash가 변경되면(위에서 변경했음), 광고로(adUrl)로 이동한다.
    • 아래의 동영상 확인
  • 즉, 걍 저 스크립트가 페이지에 있으면 무조건 url의 hash 부분을 변경하게 된다.
  • 이후, 사용자들은 페이지를 facebook등에 공유하게 되면 url의 끝에 #_enplie가 붙어 있는 url을 공유하게 되는것이다.
  •  얼마나 링크들이 많이 퍼졌는지를 트래킹하기 위한 정보로 사용하는것인지, 아니면 광고를 잘 처리 했다는 의미로 사용하는것인지는 모르겠다.

오늘은 여기까지. ㅎ.

이런이런.. 또 뜨네?

  • 그래서 이제는 코드까지 좀 뜯어 보기로

코드는?

  • YTN에 페이지에 접근했는데 광고가 또 떴다.
  • 그래서 이제는 코드를 뜯어 보기로...
  • 개발자 도구를 띄웠는데.. 에러가 나있네?

에러난쪽 코드 분석...

  • 에러는 다음의 jquery에서 시작된 것이다.
    • 이 파일을 열어 보면, mobon.net 이라는 사이트에서 jquery를 다시 긁어 오는것을 알 수 있다.
    • mobon.net 사이트에 접근해 보면, 이전에 조사한 사이트인 인라이플라는 회사가 연관되어 있는것을 알 수 있다.
      • 또한, mediacategory 사이트에 접근할때, megadata.co.kr 이라는 사이트에서 javascript를 다운 받는다. 해당 자바스크립트에는 인플라이 광고주 랜딩처리 한다고 적혀 있다.
  • 또한 해당 코드를 확인해보면 의심스러운 몇가지 행동을 하는 코드를 발견할 수 있다.
    • HTML Document에 a tag를 만들어 추가하고, click event를 발생시키는 코드. 이후 추가한 a tag를 제거하고 있다.
    • 빈 새창을 띄우고, focus를 보낸뒤, 창을 닫는 동작
    • 모바일 웹 브라우져면 동작하지 않도록
    • Safari면 동작하지 않도록
    • 볼만한 부분은 아래 부분이다. 계속해서 about:blank popup을 만들고 focus를 주고, close 시키는것을 0.5초마다 반복하도록 한다.

엇...

  • 실수로 창을 닫아 버렸다. -_-;;;
  • 오늘은 여기까지... ;;;
  1. 한수 배우고 싶습니다 2019.06.09 21:05

    수고 많으십니다. 선생님.
    #_enliple"target="_blank'>~~ 요런 해시태그를 캐다 보니 이 홈피까지 와서 많이 배우게 될 거 같은데요
    이 해시태그가 정확히 무얼 의미하는 것인지, 저 광고 회사와 어떤 연관이 있는지 정확하게 좀 알고 싶습니다.

    • 2019.06.26 13:06 신고

      헐... 저도 아직 가끔씩 광고창이 뜨고 있습니다. 크롬 플러그인에서 무언가가 있는지도 확인해 봐야 할 듯 해요.

      저 광고회사랑은 반드시 연관이 있다고 생각하고 있습니다. ^_^

  2. 돈덕후만 2019.06.10 09:30 신고

    감사합니다.
    너무 궁금한데, 실력이 미천하여 추적하지는 못하고 고수님의 글 보고 있습니다.
    막을 수 없더라도 이유는 알고 싶어서 계속 방문하겠습니다.

    • 2019.06.26 13:09 신고

      음.. 아마도 hosts 파일을 변경하는것으로 광고 뜨는것을 막을 수는 있을듯 합니다.

      https://vfxpedia.tistory.com/8

      위 글을 확인해 보시고, 해당 회사의 도메인도 등록해 주시면 동작하지 않을듯 합니다.

      잘 되면 알려 주세요 ^_^

크롬에서 가끔 광고창이 뜬다. 그것도 팝업으로..

  • 요즘에는 웹브라우져에서 기본적으로 팝업을 다 막아 둔다.
  • 그런데도 가끔씩 팝업으로 광고가 뜨는 경우가 있다.
  • 근데 이게 맨날 뜨는건 아니라서, 그냥 참고 쓰고 있었는데...

이거 안되겠다.

  • 궁금하기도 하고 말야... ㅎ.

어떤 경우에 떴었지?

  • 우선 팝업으로 광고창이 뜰 때 상황을 대략 보면
    • 새 탭으로 링크를 열때 주로 뜨더라 ( 내가 거의 모든 창을 새 탭으로 띄워서.. 그렇게 생각 된 것일수도... )
    • 새 탭으로 링크를 열면, 해당 창에서 popup이 blocking 된다는 아이콘이 여러번 나온뒤, 팝업창이 뜨고 광고가 나온다.

어떤 과정을 통해서 뜨지?

  • 크롬에서 팝업이 뜨면, "이전"으로 갈 수 없으므로, 팝업을 띄운 놈을 알기 어려운 문제가 있다.
  • 하지만, 팝업 창에서 F12나, Ctrl+Shift+I를 누르면 나오는 개발자 도구에서 정보를 얻을 수 있는데...
  • 그 중 network 상태를 보면 앞 부분에 appier.net 에 대해 연결 되는것을 볼 수 있다.
  • 그 정보를 분석해 보면
    • 출발지(referer) : www.mediacategory.com
    • URL Request : anylist.c.appier.net
    • 광고할 사이트 : dongwonmall.com

그래서 각 사이트는 뭔가?

  • URL 주소가 몇개가 있는데, 각 사이트는 뭔지 확인해 보자.

    • 광고할 사이트 dongwonmall은... 말 그대로 동원몰 이다.

    • Request를 보내는 appier.net 는 광고 마케팅 업체이다.

    • mediacategory.com 에 접근해서 정보를 보면, 많은양의 cookie 정보를 가지고 있는것을 알 수 있다.

      • mediacategoty.com 의 도메인 정보를 보면 주인이 enliple.com 인것을 알 수 있다.

      • enliple 역시 광고 플랫폼 회사다.

어떻게 크롬 팝업 block을 뚫고 뜨는거지?

  • 이건 아직 모르겠다. 다음번에 팝업 blocker를 뚥고 나올때, 다시 보고 분석하는것으로.. 끝. ㅋ.

결론

  • 광고 업체는 어떻게든.. 먹고 사는구나...
  • 이 업체에 광고를 맡긴 업체에게 뭐라고 해야, 하려나? 이런식의 광고는 사용자에게 나쁜 경험을 준다고?

읽기전

  • 인공지능으로 간단하게 만들어 본게 있는데, Keras(케라스)를 이용해서 만들었다.
  • 여러곳을 참고해 보니, 아예 연구자가 아닌 이상 케라스를 이용하면 왠만한건 할 수 있다는 이야기를 보았다.
  • 물론 간단하게 만들어 본 것 역시 케라스를 이용해서 만들었다.
  • 그래서 케라스 자체를 좀 더 알아 보는게 좋을 것이 생각해서 구매한 책.

기타

  • 보통 책과 관련없는 내용은 아랫쪽에 따로 두기도 하는데..
  • 책 자체에 역자가 많은 주석을 달아 두었다. 그래서 책을 읽기가 좋다.
  • 대부분의 이론들이나, 전망은 걍 생략했다. 이 글을 읽는 사람이 있다면, 자세한 내용은 책을 구매해서 읽으시길...
  • 초급용 책을 뗐다면, 이 책을 읽어 보는것을 추천한다. 참고로 초급용 책은 "모두의 딥러닝"을 추천한다.

책읽기

1부 딥러닝의 기초

  • 이론적인 내용 생략

1장 딥러닝이란 무엇인가?

  • 이론적인 내용 생략

인공지능과 머신 러닝, 딥러닝

  • 인공지능 : 보통의 사람이 수행하는 지능적인 작업을 자동화 하기 위한 연구 활동
  • 머신러닝 시스템은 명시적으로 프로그램 되는 것이 아니라 훈련(training)
  • 데이터 포인트 라는 말이 나오는데, 인공지능 학습에 사용되는 데이터들을 데이터 포인트 라는 용어로 잘 사용하더라. ( 직전에 읽은, 피처 엔지니어링 책에서도 데이터 포인트 라는 용어를 사용했던것 같다. )
  • 표현(representation) : 머신러닝과 딥러닝의 핵심 문제ㄴ,ㄴ 입력 데이터를 기반으로 기대 출력에 가깝게 만드는 유용한 표현을 학습하는것.
    • 핵심은 데이터를 인코딩하거나 묘사하기 위해 데이터를 바라보는 방법
    • 이미지가 RGB 혹은 HSV로 바뀌는것도 표현이 바뀌는것
    • 2차원 데이터 포인트들에서, 좌표를 변환하는것.
    • 시스템적으로 데이터 포인트를 잘 구분할 수 있도록, "학습"시킬 수 있다.
    • 이 과정중 일부는 기계가 "학습"하기 쉽게, 사람이 먼저 "피처 엔지니어링"을 해야 할 수도 있겠다.
  • 뉴럴넷은 뇌구조를 이해하는것에 영감을 만들어 진 것이다. 진짜 사람의 뇌가 그렇게 동작한다는 근거는 없다.

딥러닝 이전: 머신 러닝의 간략한 역사

  • 확률적 모델링
    • 통계학 이론을 데이터 분석에 응용
    • 나이브 베이즈 알고리즘
      • 입력 데이터의 특성이 모두 독립적이다고 가정
      • 고전적인 방법이라, 컴퓨터 등장전에는 수작업으로 적용
    • 로지스틱 회귀
      • 회귀 알고리즘이 아니라, 분류 알고리즘
  • 초창기 신경망

왜 딥러닝일까? 왜 지금일까?

  • 20년 후에도 심층 신경망을 사용하고 있을까요? ... 지금부터 20년 후에는 신경망을 사용하지 않을지도 모르지만, 딥러닝과 딥러닝의 핵심 개념에서 직접 파생된 무엇인가를 사용할 것입니다.

2장 시작하기 전에: 신경망의 수학적 구성 요소

  • 내용 생략

신경망과의 첫 만남

  • 내용 생략

신경망을 위한 데이터 표현

  • 내용 생략

신경망의 톱니바퀴: 텐서 연산

  • 내용 생략

신경망의 엔진: 그랜디언트 기반 최적화

  • 내용 생략

첫 번째 예제 다시 살펴보기

  • 내용 생략

요약

  • 내용 생략

3장 신경망 시작하기

  • 내용 생략

신경망의 구조

  • 내용 생략

케라스 소개

  • 케라스는 MIT 라이선스를 따르므로 상벚거인 프로젝트에도 자유롭게 사용할 수 있습니다.
  • 최근 딥러닝 프레임워크의 순위는 텐서플로우, 케라스 파이토치 순임.
  • 케라스는 고수준 구성 요소를 제공. 백엔드로는 텐서플로우, 씨아노, CNTK 3개의 엔진을 골라서 사용할 수 있음.
  • 케라스로 모델을 만드는 법
    • Sequential 클래스를 이용해서 순차적으로 쌓아 올리는 방법
    • 함수형 API를 사용해서, 임의의 구조를 만들 수 있는 방법

딥러닝 컴퓨터 셋팅

  • 내용 생략

영화 리뷰 분류: 이진 분류 예제

  • 내용 생략

뉴스 기사 분류: 다중 분류 문제

  • one hot encoding되어 있는 데이터라면 loss에 categorical_crossentropy를 사용하면 되고, 그렇지 않고 숫자로 라벨링 되어 있는 경우라면, loss에 sparse_categorical_crossentropy를 사용하면 된다. 굳이 바꿀 필요 없음.
  • 충분히 큰 중간층을 두어야 하는 이유
    • 마지막 출력이 46차원이기 때문에 중간에 히든 유닛이 46개 보다는 많이 적어서는 안된다. 책에서는 중간에 4차원을 두었는데, 이렇게 두어도 아예 안 되진 않지만, 4차원으로는 정보를 충분히 표현할 수 없어 79%에서 71%로 8% 정도 정확도가 감소한다.
    • 4차원에 대부분의 정보를 넣었겠지만, 그래도 다 넣지는 못한 것으로 생각할 수 있다.

주택 가격 예측: 회귀 문제

  • 데이터의 피쳐가 여러 범위를 가지고 있다. 이때는 데이터를 균일한 범위로 맞춰 주는것이 중요하다. 안되지는 않겠지만, 피쳐의 중요도를 떠나, 그냥 숫자가 클 경우 곱셈을 하게 되면 큰 변화량을 가지게 될 것이다. ( 피쳐엔지니어링 책 참고 )

  • 데이터를 정규화하는 방법

    • 피처의 평균을 빼고, 표준편차로 나누는 방식

    • 피처의 중앙이 0 근처에 맞추어지고, 표준편차가 1이 된다.

      mean = train_data.mean(axis=0)
      train_data = train_data - mean
      std = train_data.std(axis=0)
      train_data = train_data/std
      
      test_data = test_data - mean
      test_data = test_data/std
  • 일반적으로 훈련 데이터의 개수가 적을수록 과대적합(오버피팅)이 더 쉽게 일어나므로 작은 모델을 사용하는 것이 과대적합을 피하는 한 방법입니다.

  • 모델의 마지막은 1개의 유닛을 가지고 있고, 활성화 함수가 없음. 전형적인 스칼라 회귀(하나의 연속적인 값을 예측하는 회귀)를 위한 구성.

  • loss = mse : 평균 제곱 오차. 회귀 문제에서 널리 사용되는 손실 함수.

  • metrics = mae: 평균 절대 오차. 예측과 타깃 사이의 거리 절대값. 0.5면 평균적으로 500달러 차이 난다는것.( 1 = $1000 기준 )

  • 데이터량이 너무 작으면, validation set도 아까우니깐, k-겹 검증 적용

    • K-fold cross-validation : 데이터를 4덩이로 나눈다면
    • 0, 1, 2 는 학습용으로, 3은 검증용으로
    • 0, 1, 3 은 학습용으로, 2는 검증용으로
    • 0, 2, 3 은 학습용으로, 1은 검증용으로
    • 1, 2, 3 은 학습용으로, 0은 검증용으로
    • 모두 loop를 돌고 나면 각 검증용으로 사용했던 0, 1, 2, 3 의 결과를 평균내서 검증의 최종 값으로 사용.
    • 중요한건, 각 학습을 할 때 validation set의 데이터를 참고하지 않았다는 점이다.*
    • 하지만, 코드를 따로 짜야하는 불편함이... 그냥 데이터를 많이 만들어 두고 쓰자. ㅎ.

요약

  • 내용 생략

4장 머신 러닝의 기본 요소

머신 러닝의 네 가지 분류

머신 러닝 모델 평가

  • 반복 K-겹 교차 검증 : k-겹 교차 검증과 동일하나, 반복시마다 데이터를 섞은 뒤에 다시 k 개로 나누고 학습 시키는것을 반복한다.
  • 평가 방식을 선택할 때 다음의 사항을 유의 해야 함.
    • 대표성 있는 데이터 : 훈련 세트와, 테스트 세트가 주어진 데이터에 대표성이 있어야 함. 한쪽으로 쏠려 있는 데이터라면 당연히 잘못 훈련이 될 것이고 테스트도 잘못 될 것이다. 일반적으로는 데이터를 무작위로 섞어 쓰는것이 일반적.
    • 시간의 방향 : 과거로부터 미래를 예측한다면, 당연히 데이터를 섞으면 안된다.
    • 데이터 중복 : 같은 데이터가 여러개가 있는 경우, 데이터를 섞어서 훈련 세트와 테스트 세트로 만들게 되면, 훈련 세트에 있는 데이터와 테스트 세트에 있는 데이터가 동일하게 될 수 있다. 그러면 결국 테스트한 데이터가 학습 데이터에 들어 있다는 말이 된다. 그러므로 이걸 섞이지 않도록 해 주는게 중요하다.

데이터 전처리, 특성 공학, 특성 학습

  • 피처 엔지니어링 관련 내용 : 관련 내용은 다른 책을 참고하자. ㅎ
  • 벡터화 : 모든 데이터를 숫자형태(int나 float)로 바꿔야 한다.
  • 값 정규화 : 스케일이 다른 값들을 일정한 범위로 바꿔 줘야 한다. 스케일이 너무 차이나면 문제가 되기 때문이다. 일반적으로 평균을 0, 표준편차를 1로 만들어주는 작업. 대부분 0 ~ 1 사이의 값을 취하도록 한다.
  • 누락된 값 : 데이터가 누락된 경우에는 0이나 평균값, 중간값등으로 처리해도 크게 문제되지 않는다. ( 그 값 자체가 의미가 있지 않다면 말이다. ) 네트워크가 알아서 적당히 처리 할 것이다. (하지만... 확인해 보기 전에는 알 수 없지 않을까??)
  • 특성 공학(피처 엔지니어링) : 데이터를 사용하기 전에 먼저 잘 학습되도록 적당히 바꿔 주는것.
    • 이미지로 시간을 맞추는것을 한다면, 이미지를 바로 사용한다면 CNN같은걸 써야 겠지만, 단순한 이미지 처리로 바늘두개의 각도를 구할 수 있다면 더 쉽게 학습 시킬 수 있을 것이다.
    • 특성을 더 간단한 방식으로 표현하여 문제를 쉽게 만든다. 이럴려면 해당 문제를 아주 잘 이해하고 있어야 한다.
    • 딥러닝 이전에는 매우 중요 했음.
    • 다행히 최근 딥러닝은 대부분 특성 공학이 필요하지 않습니다. 신경망이 자동으로 원본 데이터에 유용한 특성을 추출할 수 있기 때문입니다. 하지만...
      • 좋은 특성은 적은 자원을 사용하여 문제를 더 잘 풀 수 있음. 시계 바늘을 읽는 문제는 굳이 합성곱 신경망(CNN)을 사용할 필요가 없음.
      • 좋은 특성은 더 적은 데이터로 문제를 풀 수 있음. 딥러닝 모델은 특성을 학습할때 많은 양의 데이터가 필요함. 샘플의 갯수가 적다면 특성을 잘 뽑아내 주는게 중요함.

과대적합과 과소적합

  • 과소적합 : 아직 학습할 껀덕지가 있는 상태
  • 과대적합 : 학습 데이터에만 너무 집중되고 있는 상태 ( 자세한건 따로 보셈 ㅋ ). 그러므로 이걸 피해야 한다. 이렇게 피하는걸 규제(regularization)라고 한다.
    • 네트워크 크기 축소
      • 네트워크의 크기가 크면, 외울 수 있는 capacity가 크고, 그러므로 학습한 데이터를 모두 외워 버릴 수 있을 정도가 될 수 있다.
      • 그러므로 일반화 시킬려면 오히려 네트워크를 줄여야 한다.
      • 우리가 필요한것은 학습 데이터를 잘 맞추는게 아니라, 다른것도 잘 맞출 수 있도록 일반화 되어야 하기 때문이다.
      • 하지만, 그렇다고 네트워크 크기를 팍 줄이면, 기억할 공간이 줄어 들기 때문에 학습이 잘 안될 거다... 그러니 절충점을 잘 찾아야 한다... (그게 쉽나.. T_T)
      • 책에 나오는 실제 검증한 그래프를 보면, 네트워크가 크면 더 빨리 과대적합이 나타나게 된다.
    • 가중치 규제(Weight regularization)
      • 오캄의 면도날 : 어떤 것에 대한 두가지 설명이 있다면 더 적은 가정이 필요한 설명이 더 옳을 것이다.
      • 네트워크의 복잡도에 제한을 두어 가중치가 작은 값을 가지도록 강제하는것. 이러면 가중치의 값의 분포가 더 균일하게 된다.
      • L1 규제 : 가중치의 절댓값에 비례하는 비용이 추가 됨(가중치의 L1노름-norm). 이 경우에는 일부 가중치 값이 0이 되는 경우가 생길 수도 있음.
      • L2 규제 : 가중치의 제곱에 비례하는 비용이 추가 됨(가중차의 L2노름) - 가중치의 파라미터를 모두 제곱하여 더한 후 이 값의 제곱근을 추가, 훈련할 때만 해당 값을 추가. 그러므로 테스트의 loss 값보다, 훈련할때의 loss 값이 더 커질 것임.
      • L2 규제를 적용하면 좀 더 과대 적합에 잘 견딤
      • L1 규제와 L2 규제를 같이 쓰는것을 엘라스틱넷(ElasticNet)이라고 부름. L1, L2 모두 기본값은 0.01로 되어 있음. 책에서는 0.001을 사용하고 있음.
    • 드롭아웃
      • 학습시 신경망의 일부를 끄는(출력을 0으로 만듬)것. (자세한것은 생략)

보편적인 머신 러닝 작업 흐름

  • 성공 지표 선택 : "성공이 무엇인가?"를 정의하는게 중요함. 정확도? 정밀도? 재현율? 고객 재방문률? 비즈니스 성공처럼 고수준의 목표와 직접적으로 연결되어 있어야 함.
    • 클래스 분포가 균일한 분류 문제에서는 정확도가 ROC AUC가 일반적인 지표
    • 클래스 분포가 균일하지 않은 문제에서는 정밀도와 재현율을 사용할 수 있음.
    • 랭킹 문제나 다중 레이블 문제에는 평균 정밀도를 사용할 수 있음.
  • 모델에 맞는 마지막 층의 활성화 함수와 손실 함수 선택
    • 문제 유형, 마지막 층의 활성화 함수, 손실 함수
    • 이진 분류, 시그모이드, binary_crossentropy
    • 단일 레이블 다중 분류, 소프트맥스, categorial_crossentropy
    • 다중 레이블 다중 분류, 시그모이드, binary_crossentropy
    • 임의 값에 대한 회귀, 없음, mse
    • 0과 1 사이 값에 대한 회귀, 시그모이드, mse 또는 binary_crossentropy

요약

  • 생략

2부 실전 딥러닝

  • 생략

5장 컴퓨터 비전을 위한 딥러닝

  • 생략

합성곱 신경망 소개

  • 생략

소규모 데이터셋에서 밑바닥부터 컨브넷 훈련하기

  • 데이터가 풍부할때만 작동한다는 말을 들음. 하지만 딥러닝은 특성을 찾는것이다. 그러므로 특성을 쉽게 찾을 수 있다면 많은 데이터가 필요하지 않을 수도 있다.
  • 특성 앱의 깊이는 네트워크에서 점진적으로 증가하지만(32에서 128까지), 특성맵의 크기는 감소합니다. ( 150x150 에서 7x7까지 - padding이 0인 경우로 계산하면 150, 148 -> 74, 72 -> 36, 34 -> 17, 15 -> 7 이 된다.). 이는 거의 모든 컨브넷에서 볼 수 있는 전형적인 패턴입니다.
  • 케라스에는 이미지를 쉽게 처리하기 위한 유틸리티가 존재한다.
    • keras.preprocessing.image
    • keras.preprocessing.image.ImageDataGenerator
    • Generator를 만들때 batch_size를 적어 두면, 전체중 그 갯수 만큼이 반환된다.
    • 나중에 fit_generator 할 때는 step_per_epoch * batch_size 가 전체가 되도록 만들어 주어야 한다.
    • 리스트와 달리 반복자와 제너레이터는 전체 항목을 미리 만들지 않기 때문에 메모리에 효율적입니다.
  • 데이터 증식(data augmentation - 데이터 오그멘테이션)
    • 데이터의 숫자가 너무 작으면 데이터 갯수를 늘려주는것이 좋다.
    • ImageDataGenerator에서 아래 옵션을 주면, 속성에 맞게 이미지를 더 생성한다.
      • rotation_range : 랜덤하게 사진을 회전(0~180)
      • width_shift_range : 이미지를 평행 이동 (1 이하면 비율, 이상이면 pixel)
      • height_shift_range : 이미지를 수직 이동 (1 이하면 비율, 이상이면 pixel)
      • sher_range : 이미지를 비뚤게 회전 시킬 각도 범위
      • zoom_range : 확대할 범위
      • horizontal_flip : 이미지를 수평 대칭 변환 ( 얼굴, 풍경 등, 글자가 있는것은 수평 대칭 변환하면 안됨 )
      • fill_mode : 회전, 가로/세로 이동시 새롭고 생긴 픽셀을 채울 전략
    • 검증 데이터셋은 데이터 증식(data augmentation)을 하면 안됨. 오직 학습 데이터 셋에서만 할 것.

사전 훈련된 컨브넷 사용하기

  • 데이터 셋이 너무 작으면 어차피 잘 안되니깐, 이미 많은 양의 데이터로 만들어진 잘 학습된 모델을 활용해서 해보자는 방법.
  • 많은 양의 데이터로 잘 학습된 모델은, 내가 필요로하는 특성을 정확하게 잘 찍어 낼 순 없겠지만, 일반적인 특성은 잘 찍어 낼 수 있을 것이므로 이걸 활용하는것이 더 좋을 것임.
  • 실제 필요한것과는 다를지라도, 이론적으로는 효율적임.
  • 책에서는 VGG넷을 사용함. VGG16은 최신것도 아니고, 제일 좋은것도 아니지만, 이 모델 구조가 이전에 보았던것과 비슷해 새로운 개념을 도입하지 않고 이해를 쉽게 할 수 있기 때문에 사용.
  • 일반적으로는 합성곱(Convolution)부분만 재사용함.
    • 합성곱 층은 "학습된 표현이 더 일반적이어서 사용 가능" : 아마도, 합성곱층은 이미지 필터를 거치면서 나오는 특징을 그대로 쓰고, 같은 이미지 필터를 여러곳에서 사용할 수 있기 때문이라고 보임.
    • 하위층은 엣지, 색깔, 질감등의 특성을 뽑고,
    • 상위측은 눈이나 귀처럼 추상적인 개념을 추출
    • 만약, 새로운 데이터셋이 학습된 모델의 데이터셋과 많이 다르다면, 하위층만을 사용하는것도 하나의 방법.
    • 재사용시 trainable값을 False로 줘서, 사전 학습된 표현이 업데이트 되지 않도록 하는것이 중요함.
  • 미세 조정(파인튜닝 - fine tuning)
    • 이전에는 학습된 모델의 top만 제거하고, 새로운 layer를 붙여서, 새 layer만 학습하는 방식으로 재활용 했다.
    • 하지만, 동결 시켜 두었던 부분도 일부를 학습 시키는 방법을 쓸 수도 있다.
      • 사전에 훈련된 기반 네트워크 위에 새로운 네트워크 추가
      • 기반 네트워크 동결 후, 새로 추가한 네트워크 훈련
      • 기반 네트워크에서 일부 층을 동결 해제 한 후, 새로 추가한 네트워크와 같이 학습
    • 합성곱의 하위층은 일반적이고, 재사용가능한 특성을 학습하므로 그대로 사용하고, 상위층은 특화된 특성을 인코딩하므로, 이 부분만 다시 학습 시킨다.
  • 손실 곡선이 향상되지 않았으나, 정확도가 높이진 이유?
    • 손실 값 그래프는, 각 손실의 평균이다. 그러므로 전체의 정확도와는 별개이다. 손실 값이 큰것들은 아예 많이 커져 버리고, 나머지는 손실값을 줄이고 잘 맞추게 업데이트 된다면, 손실 값의 평균은 유지 되면서, 정확도는 높아 질 수 있다.

컨브넷 학습 시각화

  • 생략
  • CAM 을 사용하면, 이미지의 어느 위치가 분류에 영향을 미쳤는지 알 수 있다.
  • 생략

요약

  • 생략

6장 텍스트와 시퀀스를 위한 딥러닝

  • 텍스트(단어의 시퀀스), 시계열 또는 이반적인 시퀀스를 처리 할 수 있는 모델을 살펴 볼 것임
  • 시퀀스 데이터를 처리하는 기본적인 모델
    • 순환신경망(recurrent neural network, RNN)
    • 1D 컨브넷(1D convnet)
  • 시퀀스 데이터 형태로 처리하는 것들
    • 문서 분류나 시계열 분류, 글의 주자네 책의 저자 식별
    • 시계열 비교, 두 문서의 관련성, 주식 가격의 관련성
    • 시퀀스-투-시퀀스 학습, 영어 문장을 프랑스어로 번약하기
    • 감성 분석. 트윗이나 영와 리뷰가 긍정적인지 부정적인지 분류하기
    • 시계열 예측. 최근 어떤 지역의 날씨가 주어졌을때, 날씨 예측하기
  • 책에서는 IMDB의 감정분석과, 기온 예측만 집중하여 볼 것임.

텍스트 데이터 다루기

  • 문서 분류, 감성 분석, 저자 식별, (제한된 범위의) 질문 응답 등에 적합

  • 이런 딥 러닝 모델이 사람처럼 진짜 텍스트를 이해하는것은 아님

  • 문자 언어(written language)에 대한 통계적 구조를 만들어 간단한 텍스트 문제를 해결 하는 것임.

  • 컴퓨터 비전이 픽셀에 적용한 패턴인식인 것처럼, 자연어 처리를 위한 딥러닝은 단어, 문장, 문단에 적용한 패턴 인식

  • 텍스트 역시, 그대로 사용하지 못하고 숫자 형태로 바꿔 줘야 함.

  • 텍스트를 숫자 형태로 바꾸는것을 텍스트 벡터화(vectorizing)이라고 함

    • 텍스트를 단어로 나누고, 각 단어를 하나의 벡터로
    • 텍스트를 문자로 나누고, 각 문자를 하나의 벡터로
    • 텍스트에서 단어나 문자 n개를 뽑은 뒤에, 그 조합을 벡터로
    • 텍스트를 일정 기준으로 나눈것을 토큰이라고 함. 이런 토큰을 잘 처리해서 벡터를 만들 수 있음.
  • 원핫인코딩

    • 텍스트도, 단어별로 쪼갠 뒤, 각 단어를 원핫인코딩으로 바꿀 수 있다.
    • 원핫인코딩으로 바꿀때, 텍스트가 아닌 경우를 대비하여 1개를 비워 두는 센스를 발휘하자.
    • keras.preprocessing.text.Tokenizer(num_words=1000)을 사용하면, 가장 빈도가 높은 1000개 단어만 사용하도록 할 수 있음.
    • 원핫해싱이라고, 인덱스를 따로 설정하지 않고, key를 value의 hash 값을 사용하도록 한다. 바로바로 데이터를 찍을 순 있겠지만, hash 된 값이 겹쳐 버리는 문제가 발생할 수 있다.
  • 단어 임베딩(워드 임베딩, word embedding)

    • 책에서는 밀집 단어 벡터(word vector)이라고 적혀 있는데, 전체를 영어로 적으면 dense word vector이다. dense를 보통 밀집이라고 해석하는데, 의미 없이 공간을 차지하는 정보가 없는 정도로 해석하면 좋겠다. 원핫인코딩의 경우 많은 값들이 0 이고, 딱 1개만 1이기 때문에 0은 의미가 없다(이런 애들을 희소(sparse)하다고 한다). 그러므로, 14번째 위치에 1이 있다고 표현하는 ( 14, 1 ) 이라고 표현하면 dense하게 표현되었다고 볼 수 있다.
    • keras.layers.Embedding(1000,64)는, 1000개의 단어를 64차원으로 표현하겠다는 것이다.
    • Embedding을 만들고, dense를 만들어 붙인 후에 데이터를 fit으로 때려 박으면, 알아서 잘 분리한 vector가 만들어 진다.
    • 임베딩 알고리즘에는 Word2Vec나 GloVe 같은게 있다.
    • 당근, 데이터셋이 작다면, 사전 학습된 모델을 읽어와서 재활용하고, 필요한 부분만 덧붙여 쓰는게 좋다.
    • 순환 신경망 이해하기

  • RNN, LSTM 설명, 생략.

순환 신경망의 고급 사용법

  • 순환 드롭아웃 : 순환층에서 과대적합을 방지하기 위해 사용. 케라스에 내장되어 있음. ( GRU나 LSTM에 dropout 값을 줄 수 있음 )
  • 스태킹 순환 층 : 순환층의 마지막 노드의 결과만 내 뱉는게 아니라, 모든 노드의 결과를 연결해 주는 형태 ( return_sequences 값을 이용해서 처리 할 수 있음 )
  • 양방향 순환 층 : 데이터를 a, b, c, d 순으로 입력하던것을 d, c, b, a 순으로도 입력하는 branch 층을 만든다.

컨브넷을 사용한 시퀀스 처리

  • 벡터를 RNN으로 계속 순환 시킬것이 아니라, CNN 1D로 계산하는 방식
  • CNN으로 계산하면 훨씬 속도가 빨라진다.
  • 1D CNN으로 특징을 먼저 뽑아내고, RNN을 돌릴 수도 있다.

7장 딥러닝을 위한 고급 도구

Sequential 모델을 넘어서: 케라스의 함수형 API

  • 기존에는 순차적으로 연결한 모델만 만들 수 있었다.

  • 하지만, 함수형 API를 사용하면, branch를 만들거나, merge 할 수 있다.

  • 일반적인 Sequence Model을 함수형 API로 표현

    input_tensor = Input( shape=(64,) )
    x = layers.Dense(32, activation='relu')(input_tensor)
    x = layers.Dense(64, activation='relu')(x)
    output_tensor = layers.Dense(10, activation='softmax')(x)
    
    model = Model(input_tensor, output_tensor)
  • 2개 이상의 vector을 받아서, 1개의 출력으로 내는 경우

    text_input = Input( shape=(...) )
    embedded_text = layers.Embedding(....)(text_input)
    encoded_text = layers.LSTM(...)(embedded_text)
    
    ques_input = Input( shape=(...) )
    embedded_quest = layers.Embedding(....)(ques_input)
    encoded_ques = layers.LSTM(...)(embedded_ques)
    
    concatenated = layers.concatenate([encoded_text, encoded_ques], axis=-1) 
    
    answer = layers.Dense(64, activation='softmax')(concatenated)
    
    model = Model ( [text_input, ques_input] , answer )
    
    model.compile( optimizer='rmsprop', loss='categorical_crossentropy' ) # 1개의 output이므로 optimizer나 loss 는 1개 만 설정하면 된다. 
    
    model.fit ( [text, ques], answer, ... ) # 2개의 Input과 1개의 Output이다.
  • 2개 이상의 출력을 내는 경우

    # 나머지는 비슷하게 하고, 제일 마지막 출력층에 대한 것만...
    age_predict = layers.Dense(1)(x)
    
    income_predict = layers.Dense(100, activation='sfotmax'(x)
    
    gender_predict = layers.Dense(1, activation='sigmoid')(x)
    
    model = Model ( input, [age_predict, income_redict, gender_predict]) # 1개의 Input과 3개의 Output에 대해서 처리해야 한다.
    model.compile( optimizer='rmsprop', loss = ['mse'm 'categorical_crossentropy', 'binary_crossentropy'] ) # 3개의 Output에 대한 각각의 정보가 필요하다.
    # 필요할 경우 compile 옵션으로 loss_weight=[1.0, 0.25, 10.] 등, loss 값에 가중치를 줄 수도 있다.
    
    model.fit ( posts, [age_targets, income_targets, gender_targets], ... ) # 입력이 1개, 출력이 3개다.
  • 인센셥 모델의 경우 branch를 따고, 합치는 과정이므로, 이 글에서는 따로 설명하지 않고 pass.

  • 잔차연결(residual connection)

    x = layers.Conv2D(...)(x)
    y = layers.Conv2D(...)(x)
    y = lqyers.Conv2D(...)(y)
    
    y = layers.add( [ y, x ] ) # 마지막 y의 특성에 x의 출력 특성을 더한다.
  • 기존의 모델을 layer 처럼 사용 가능

    xception_base = application.Xception(weight=None, include_top=False)
    input = Input(shape=(250, 250, 3))
    features = xeception(input)    

케라스 콜백과 텐서보드를 사용한 딥러닝 모델 검사와 모니터링

  • 콜백 : 콜백을 직접 만들 수도 있지만, 이 글에서는 중요한거만...

    • ModelCheckpoint : epochs 마다 모델을 저장한다.

    • EarlyStopping : validation loss가 일정 횟수 이상, 줄어 들지 않으면 자동으로 멈춘다.

    • ReduceLROnPlateau : validation loss가 향상되지 않으면, 학습률을 작게 할 수 있음.

    • 예제

      callbacks_list = [
      // val_acc 값이 patience 만큼 횟수의 epoch를 돌았는데도, 정확도가 늘지 않으면 멈춘다.
      keras.callbacks.EarlyStopping( monitor='val_acc', patience=1),
      
      // epoch 마다 my_model.h5에 저장한다. 단, val_loss 값이 줄어들지 않으면, 모델을 덮어쓰지 않는다.
      keras.callbacks.ModelCheckpoint(filepath='my_model.h5' , monitor='val_loss', save_best_only=True),
      
      // val_loss 값을 확인해서 10번동안 줄어들지 않으면, 학습률을 1/10 으로 줄인다.
      keras.callbacks.ReduceLROnPlateau( momitor='val_loss',factor=0.1, patience=10 );
      ]
      
      // callback에서 val_loss 값을 사용하기 때문에, metrics에 acc 값이 포함되어 있어야 한다.
      model.compile( optimizer='rmsprop', loss='binary_crossentropy', metrics=['acc'] )
      
      // epoch 마다, callbacks_list에 있는 callback들을 호출한다. 이 callback에서 val_acc 값을 사용하기 때문에, 꼭 validation_data 값이 필요하다.
      model.fit( x, y, epochs=10, batch_size=32, callbacks = callbacks_list, validation_data=(x_val, y_val))
  • 텐서보드 : 텐서플로우일때만 사용할 수 있자만 참 유용함

    • TensorBoard : 훈련하는 동안의 지표, 모델 구조 확인, 활성화 출력, 3D 임베딩 등을 쉽게 볼 수 있음

    • 예제

      callbacks = [
        // 학습 로그는 my_log_dir에 남기며, 1 epoch마다, 활성화 출력과 임베딩 데이터를 기록.
        keras.callbacks.TensorBoard( log_dir='my_log_dir', histogram_freq=1, embeddings_freq=1 )
      ]
    • python 코드를 실행 시킨 후 shell에서 tensorboard --logdir=my_log_dir 실행후, http://localhost:6006 에 접속하면 볼 수 있음.

  • 모델 시각화

    • TensorBoard를 사용하면 모델 시각화를 할 수 있지만, tensorflow의 모델 형태로 나오기 때문에 보기가 어렵다.

    • 케라스 모델을 쉽게 볼 수 있게 이미지로 만들 수 있는 방법도 있다.

      from keras.utils import plot_model
      // 케라스 모델인 model을 보기 쉽게 model.png 파일에 이미지로 떨어뜨려 준다.  
      // show_shapes = True, layer의 input과 output의 shape을 같이 보여준다.  
      // show_layers_name = True, layer 이름을 같이 보여 준다.  
      // rankdir = TB | LR, TB면 수직으로, LR 수평으로 그려준다.  
      plot_model ( model, to_file='model.png', show_shapes=True )

모델의 성능을 최대로 끌어올리기

  • 배치 정규화

    • 배치 정규화를 사용하면 더 깊은 네트워크를 구성할 수 있다.

    • BatchNormalization은 일반적으로, 합성곱이나 환전 연결층 다음에 사용함

      conv_model.add( layers.Conv2D(32, 3, activation='relu') )
      conv_model.add( layers.BatchNormalization() )
      
      dense_model.add( layers.Dense(32, activation='relu') )  
      dense_model.add ( layers.BatchNormalization() )  
    • 배치 정규화클래스는 특성 축을 지정할 수 있는 axis 매개 변수가 있음. ( 기본값 -1, 입력텐서의 마지막 축 )

    • data_format을 "channels_last"로 하여, Dense, Conv1D, ENN, Conv2D 층을 사용할 때 맞는 값.

    • data_format이 "channels_first"라면, 특성축이 1이므로, axis=1 로 주어야 함. ( 0번째 축은 "배치"차원 축 )

  • 깊이별 분리 합성곱 ( depthwise separable convolution )

    • Conv2D 보다 가볍고, 빠르다. 성능도 좋다.
    • 적은 데이터로도 좋은 표현을 학습하고, 결국 성능이 더 좋은 모델을 만듬. 제한된 데이터로 작은 모델을 만들때 중요.
    • 예제는 Conv2D를 사용하는곳에 모두 layers.SeparableConv2D를 사용하는 형태로만 바꾸면 됨.
  • 하이퍼 파라미터 최적화

    • 규칙은 없다. 자동으로 하이퍼 파라미터를 찾아주는건 연구되고 있는 과정
    • 관련 라이브러리 : Hyperopt, Hyperas(Hyperopt와 연동하여 keras에서 사용가능), Auto-Keras, auto-sklearn
  • 모델 앙상블(model ensemble)

    • 하나의 목적을 가진 여러가지 모델을 만들고, 각 모델별 예측치를 평균하여 찾는 방법
    • 한가지 모델은 편향되어 있을 수 있지만, 여러가지 편향을 가진 각 모델을 평균내면 오히려 더 잘 동작할 수도 있다.

8장 생성 모델을 위한 딥러닝

LSTM으로 텍스트 생성하기

  • 생략

딥드림

  • 내가 별로 관심이 없어서 생략. ㅎ. 책도 대충 읽고 넘김. ㅎ.

뉴럴 스타일 트랜스퍼

  • 생략

변이형 오토인코더를 사용한 이미지 생성

  • 생략

적대적 생성 신경망 소개

  • GAN(Generative Adversarial Netowkrs)
  • 모델은 크게 두가지로 나뉨. 한쪽에서는 이미지를 생성, 한쪽에서는 생성된 이미지가 진짜/가짜인지 판단
  • 양쪽을 모두 학습 시킨 뒤, 생성 부분만 모델만있으면, 이미지를 생성할 수 있음.
  • 대충은 아니깐, 자세한건 생략.

이하 항목 생략

발단

요즘에 이것저것 한다고, javascript들을 좀 해 보고 있는데, 배열에 여러가지 작업을 쉽게 할 수 있어 좋은 함수들이 있어, 계속 쓰다가, 나중을 위해 정리 하려고 간단하게 기록.

배열을 loop 돌면서 무언가를 하고 싶다면 아래 함수들을 활용하자.

  • forEach : 한개씩 돌면서 무언가 하기, return value는 없음.
  • filter : 조건에 맞는것만 새로운 배열로. return value는 새 배열.
  • map : 한개씩 돌면서 연산한 결과를 새로운 배열로. return value는 새 배열
  • reduce : 한개씩 돌면서 이전 연산한 결과를 조합하여 사용하기. return value는 reuce 함수안에서 설정한 대로.
    • 무슨 말인지 이해가 어려울 수도 있는데... 알면 쉬움... ;;

간단한, forEach, filter, map 부터

  • 이해하기 쉽도록 되도록이면 쉬운 예제를 만들어 보았다.

forEach - 한개씩 돌면서 무언가 하기

["a", "b", "c"].forEach ( 
    function(x) {
        console.log(x);
    }
)
  • 결과 : 화면에 a, b, c 가 출력 된다.

filter - 배열에서 조건에 맞는것만 새로운 배열만들어 반환하기.

[ 1, 2, 3, 4, 5].filter(
    function(x) {
        return x % 2 == 0;
    }
)
  • 결과 : [ 2, 4 ] 배열이 반환된다.

filter + forEach - 조건에 맞는것만 배열로 만들어, 한개씩 돌면서 무언가 처리 하기

[ 1, 2, 3, 4, 5].filter(
    function(x) {
        return x % 2 == 0;
    }
).forEach ( 
    function(x) {
        console.log(x);
    }
)
  • 결과 : 화면에 2, 4 가 출력 된다.

map - 배열의 각 요소에 무슨짓한 결과를 새 배열로 반환

[ 1, 2, 3, 4, 5].map(
    function(x) {
        return x * 2;
    }
)
  • 결과 : [2, 4, 6, 8, 10] 배열이 반환된다.

map + forEach - 배열의 각 요소에 어떠한 연산을 하고, 그 결과를 하나씩 돌면서 무슨 짓을 하기

[ 1, 2, 3, 4, 5].map(
    function(x) {
        return x * 2;
    }
).forEach ( 
    function(x) {
        console.log(x);
    }
)
  • 결과 : 화면에 2, 4, 6, 8, 10 이 출력 된다.

filter + map + forEach - 배열에서 원하는 요소만 뽑아내고, 그 결과 배열에 어떠한 연산을 하고, 그 결과를 하나씩 돌면서 무슨짓을 하기

[ 1, 2, 3, 4, 5].filter(
    function(x) {
        return x % 2 == 0;
    }
).map(
    function(x) {
        return x * 2;
    }
).forEach ( 
    function(x) {
        console.log(x);
    }
)
  • 결과 : 화면에 4, 8 이 출력 된다.

조금 까다롭지만 활용성이 매우 좋은 reduce

  • reduce는 배열의 순환을 돌면서, 이전 결과를 활용하는 방식이다.
  • forEach, filter, map 과 같이 reduce도 내부에서 함수를 1개 받는데, 파라미터에 여러가지 정보가 들어온다.
  • 함수는 function ( ac, current, index, array ) 4개의 파라미터를 받는다.
    • ac : reduce 호출할때 넘긴 함수의 결과를 보관. 최초 호출될때는 reduce를 호출할때 두번째 넘김 파라미터의 값.
    • current : 배열의 0 번 부터 배열의 마지막까지 순차적으로 전달 됨
    • index : 현재 배열의 몇번째를 loop 돌고 있는지 알려 주는 값
    • array : reduce 함수를 호출한 배열.
  • 긴 설명은 설명이 잘 되어 있는 다른 사이트에서 찾도록 하자.
  • reduce 함수에서 위 4가지 파라미터를 활용하면, filter, map, forEach 를 모두 구현할 수 있다.
  • 즉, reduce 짱짱임.

reduce - 숫자가 들어 있는 배열의 합 구하기

[1, 2].reduce (
    function ( ac, current, index, array ) {
          // 최초 호출될때, ac는 reduce의 두번째 파라미터인 아래에서 넘긴 0 이고,, current는 배열의 0 번째인 1이 들어 있을 것이다.
          // 그러므로 최초 호출 될 때는 return 값이 0 + 1 이므로, 1이 return 될 것이다.
          // 두번째 호출 될 때는 ac는, 첫번째 호출 되었을때, return한 값인 1 값을 가지고, current는 배열의 1번째 2가 들어 있을 것이다.
          // 그리고 두번째 호출 될 때는 return 값이 1 + 2 인 3 이 될 것이다.
          // 더 이상 loop를 돌 아이템이 없으므로, 해당 함수의 리턴값의 3 이 될 것이다.
        ac = ac + current;
        return ac;
    }
,0); // reduce 함수의 두번째 파라미터인 0 은, 위 익명 함수의 ac에 최초 할당 된다.
  • 결과 : 3이 반환 될 것이다.

reduce - string 배열을 순환하면서 모든 배열 item을 1개의 string으로 합치기

[ "안녕", "하세요" ].reduce(
    function ( ac, current, index, array ) {
          // 최초 호출될때, ac는 reduce의 두번째 파라미터인 아래에서 넘긴 "" 값을 가지고, current는 배열의 0 번째 "안녕"의 값이 들어 있을 것이다.
          // 그러므로 최초 호출 될 때는 return 값이 "" + "안녕" 이므로, "안녕"이 return 될 것이다.
          // 두번째 호출 될 때는 ac는 첫번째 호출 되었을때, return한 값인 "안녕" 값을 가지고, current는 배열의 1번째 "하세요"가 들어 있을 것이다.
          // 그리고 두번째 호출 될 때는 return 값이 "안녕"+"하세요"가 될 것이다.
          // 더 이상 돌 item이 없으므로, 결과적으로 해당 함수의 return 값은 "안녕하세요"가 될 것이다.
        return ac + current; 
    }
, "" ) // reduce 함수의 두번째 파라미터인 "" 은, 위 익명 함수의 ac에 최초 할당 된다.
  • 결과 : "안녕하세요" 라는 값이 반환된다.

응? reduce 대신 forEach만 써도 되는거 아닌가?

  • 위 예제들을 사실, forEach만 사용해도 된다.

  • forEach를 사용해서 바로 위의 예제를 구현해 보자.

    let sumString = ""
    ["안녕", "하세요"].forEach(
        function (x) {
            sumString = sumString + x;
        }
    );
  • 위 예제와 주석이 제거된 reduce를 예제를 비교해 보자.

    let sumString = [ "안녕", "하세요" ].reduce(
        function ( ac, current, index, array ) {
           return ac + current; 
        }
    , "");
  • 결과는 동일하지만,

    • forEach는 배열의 loop 결과를 저장하기 위해서, sumString을 선언후 ""를 할당한 뒤 사용해야 했지만,
    • reduce는 배열의 loop 결과를 바로, sumString으로 할당 할 수 있다.

reduce - 배열에서 string type만 Set으로 만들기

[ 1, "안녕", "2", 3].reduce(
    function ( ac, current, index, array ) {
          // 최초 호출될때, ac는 reduce의 두번째 파라미터인 아래에서 넘긴 new Set() 값을 가지고, current는 배열의 0 번째 값인 1이 들어 있을 것이다.
          // 1은 string type이 아니므로, 그냥 ac를 반환한다.
          // 두번째 호출 될 때는 ac는 첫번째 호출 되었을때, return한 값인 new Set()이 그대로 들어 있을 것이고, current는 배열의 1번째 값인 "안녕"이 들어 있을 것이다.
          // "안녕"은 string type이므로, ac.add(current)를 이용해서 Set에 "안녕"을 넣는다. 그리고 ac를 반환한다.
          // 세번째 호출 될 때는 ac는 두번째 호출 되었을때, return한 값인 "안녕"이 들어 있는 Set이 들어 있을 것이고, current는 배열의 2번째 값인 "2"이 들어 있을 것이다.
          // "2"은 string type이므로, ac.add(current)를 이용해서 Set에 "2"을 넣는다. 이제 Set에는 "안녕"과 "2"가 들어 있다. 그리고 ac를 반환한다.
          // 네번째 호출 될 때는 ac는 세번째 호출 되었을때, return한 값인 "안녕"과 "2"가 들어 있는 Set이 들어 있을 것이고, current는 배열의 3번째 값인 3 이 들어 있을 것이다.
          // 3은 string type이 아니므로, "안녕"과 "2"가 들어 있는 ac를 반환한다.
          // 더 이상 돌 item이 없으므로, "안녕"과 "2"가 들어 있는 ac를 최종 반환하고 끝낸다.
        if ( typeof current == "string" ) {
            ac.add(current);
        }
        return ac;
    }
, new Set()); // reduce 함수의 두번째 파라미터인 new Set()은, 위 익명 함수의 ac 에 최초 할당된다.
  • 결과 : "안녕"과 "2"가 들어 있는 Set이 반환된다.

위 예제도, filter와 map 같은걸로 가능할 것 같은데?

  • 당근 가능하다. 위 예제는 Set을 반환했지만, filter + map과 reduce의 비교를 위해, 배열을 반환하도록 코드를 수정하겠다. 그리고 각 배열의 마지막에 "하세요"라는 문자를 추가하도록 하겠다.

  • 우선 filter + map 을 사용해서, 배열에서 string type만 array로 만들어 보자.

    [ 1, "안녕", "미안", 3].filter(
        function ( x ) {
           return typeof x == "string";
        }
    ).map(
        function ( x ) {
           return x + "하세요";
        }
    );
  • 그리고 reduce를 활용해, 배열에서 string type만 array로 만들어 보자..

    [ 1, "안녕", "미안", 3].reduce(
        function ( ac, current, index, array ) {
           if ( typeof current == "string" ) {
               ac.push(current + "하세요");
           }
           return ac;
        }
    , []);
  • 결과는 동일하지만,

    • filter와 map의 조합은 결과를 내기 위해서 배열의 loop를 두번 돌아야 하고, 정확하게는 item 을 6번 가지고 와야 한다. ( filter에서 4번, map에서 2번)
    • reduce는 배열을 한번의 loop를 돌면서 결과를 만들어 낼 수 있다. 정확하게는 item을 4번 가지고 오면 된다.

결론?

  • 처음에는 공부하기도 귀찮고 해서, 안 썼었는데...
  • 다른 강좌를 보다가 예제중에서 이걸 사용하는것들이 있어, 공부를 하게 됐다.
  • 지금은?
    • 거의 모든 배열의 loop는 이 함수들을 이용해서 처리하고 있다.
    • 익숙해 지니깐, 참 편하더라고...

읽기전

  • 데이터를 많이 들여다 보려고 노력하고 있는데, 이거 참 기본이 있어야지...

  • 특히 데이터를 어떻게 들여다 볼 것인가? 에 대한 고민이 필요해서 구매 한 책.

  • 기존 딥러닝 책들은, 이미 잘 정제 되어 있거나, 필요한 값들을 이미 선별해 둔 책이 많다.

  • 하지만, 실제 데이터들은 잘 정제되어 있지도, 어떠한 값을 딥러닝에 넣어야 할지도 모르니....

  • 에라, 모르겠다. 걍 딥러닝에 다 때려 박으면 되지 싶다가도,

    • 그래도 기본은 알아야지.
    • 필요한 것만 때려 박으면 더 잘 되겠지.
  • 싶어서 구매한 책

  • 이 책에 있는 대부분의 예제는 전체 소스코드가 나와 있지 않고, 설명이 생략 된 것도 꽤나 된다.

  • 그러므로 초보자가 읽기에 적당하지 않은듯 하다.

책 읽기

서문

옮긴이의 말

  • 하지만 너무나 다양한 데이터의 종류가 특성에 따라 경험적으로 수행돼 왔을 뿐, 이를 범용적으로 적용하는 방법에 대한 책이나 논문이 거의 없었다.
  • 머신 러닝 입문자들에게는 피처 엔지니어링에 대한 원리를 배우고 실습을 통해 실력을 높일 수 있는 좋은 기회가 될 것이며, 데이터 과학에 종사하는 분들에게는 그동안 경험적으로 수행해 오던 피처 엔지니어링 기법들을 암묵지에서 형식지로 정리하는 계기가 될 것이다.

들어가며

  • 모델은 피처(feature)를 입력으로 사용한다. 피처는 원시 데이터의 숫자적인 표현이다..
  • 피처 엔지니어링은 원시 데이터로부터 피처를 추출하고 이를 머신 러닝 모델에 적합한 형식으로 변환하는 작업이다.
  • 데이터와 모델은 매우 다양하기 때문에 피처 엔지니어링 방법으로 일반화 하기 어렵다.

1장 머신 러닝 파이프라인

데이터

  • 데이터, 모델, 피처, 모델 평가
    • 실제 세계의 현상에 대한 관측 결과
    • 데이터의 각 조각은 현실의 제한된 한 측면에 대한 창을 제공
    • 원시 데이터는 숫자가 아닌 경우가 많다. ( 앨리스가 수요일에 책을 샀다. )
    • 피처는 원시 데이터의 숫자적인 표현이다.
    • 우리가 해결하고자 과제에 적합한 모델에, 잘 들어 맞는 피처를 만들어야 한다.
    • 피처가 적으면 제대로 과제를 수행하지 못하고, 피처가 많아도 필요 없는 피처로 인해 모델의 학습에 많은 비용과 어려움이 있을 수 있다.
  • 원본 소스가 통찰력까지 가기는...
    • 소스 ->(추출 및 통합)-> 원시 데이터 -> (정제 및 변환) -> 피처 -> 모델링 -> 통찰력
    • 여기서 "정제 및 변환" 부분이 피처 엔지니어링 부분이다.

2장 숫자를 위한 멋진 트릭

  • 이미 숫자는 수학적 모델로 처리하기 쉬운 형식.
  • 하지만 좋은 피처는 데이터를 가장 두드러진 특징을 표현할 뿐만 아니라, 모델의 가정에도 맞아야 한다. 그러므로 피처 엔지니어링이 필요.
  • 고려사항
    • 값의 크기 : 양수? 음수?, 구간을 나눠야하나? 숫자가 누적되나?
    • 스케일 : 가장 큰 값, 가장 작은 값, 둘의 차이가 몇자리 수. 출력 값이 커질 수 있나? 출력값이 바이너리면?
    • 숫자 피처의 분포
    • 여러 피처를 조합해 더 복잡한 피처를 만들 수도 있음

스칼라, 벡터, 공간

  • 스칼라(scalar) : 단일 숫자 피처
  • 벡터(vector) : 방향이 있는 스칼라의 리스트, 벡터는 벡터공간내에 위치.
  • 벡터는 공간상의 한 점( 종종 원점에서 그 점까지의 선이나 화살표로 그린다. )

카운트 처리

  • 노래나 영화를 플레이 한 횟수 등 이런 카운트
  • 누군가가 조작하기가 쉬우므로, 그래도 사용할지, 존재 여부만 처리 할지, 몇개의 구간으로 나눌지 등을 고민해야 한다.

바이너리 변환

  • '견고한 척도'(통계 용어에서 "견고함"은 해당 기업이 매우 다양한 조건하에서도 잘 작동함을 말한다. 라는 말이 있는데.. 이걸 이쪽 세상에서는 로버스터(robust)라는 용어를 훨씬 더 많이 사용한다.
  • 데이터의 값이 너무 많이 차이가 나면, 그냥 1 과 0 으로 나눠 주는것도 가능하다.

양자화 또는 비닝

  • 비닝(binning)은 구간화 정도로 생각하면 되겠다.
  • 양자화랑 비슷한 듯.
  • 쉽게 말하면, 값을 구간을 두고 정리 한다는것. ( 10대, 20대, 30대 등 )
  • 고정폭 비닝
    • 나이를 가지고 할 것이라면, 10대, 20대로 할 수도 있지만, 삶의 단계에 맞게, 초등학교, 중학교, 고등학교, 대학교의 나이로 나누는것이 더 좋을 수도 있다.
    • 여러 자리수라면, 0 ~ 9, 10 ~ 100, 100 ~ 1000 등으로 나눌 수도 있다.
  • 분위수(quantile) 비닝
    • 그냥 고정폭 비닝은, 중간에 빈 값이 많으면 데이터가 없는 구간이 너무 많다.
    • 걍 전체 값의 1/2이나 1.4 단위, 혹은 1/10 단위로 나눠서 배치한다.

로그 변환

  • 작은 숫자가 많고, 큰 숫자가 듬성 듬성 적게 데이터가 존재한다면, 작은 숫자들을 좀 더 잘게 쪼개야 하고, 큰 숫자를 좀 더 모아줘야 한다.
  • 이럴때는 로그 변환을 사용하면 된다.
  • log10(x) 는
    • 1 ~ 10 사이의 숫자를 0 ~ 1 사이로 배치
    • 10 ~ 100 사이의 숫자를 1 ~ 2 사이로 배치
    • 100 ~ 1000 사이의 숫자를 2 ~ 3 사이로 배치 할 수 있다.
  • 즉, 큰 수의 변화량을 작은 변화량으로 바꿀 수 있어, 상대적으로 작은 숫자의 변화량을 더 잘 표현할 수 있게 된다.
  • 뒤에 Box-Cox 라는것도 나오는데, 잘 모르겠지만, 결국 데이터를 잘 분산한다는것에 목적이 있는 듯 하다.

피처 스케일링 또는 정규화

  • 위도나 경도는 피처의 숫자 값에 한계가 있음. 하지만 카운트는 한계가 없음.
  • 모델이 입력 피처의 스케일링(값 범위)에 민감하다면, 피처를 적절히 스케일링 해 주어야 한다.
  • 이걸 피처 스케일링, 혹은 피처 정규화(normalizataion)이라고 부른다.

min-max 스케일링

  • 제일 작은 값을 0, 제일 큰 값을 1로 변환
  • min-max scailing

표준화(분산 스케일링)

  • 피처 표준화(standardization) : 모든 데이터 포인트에 대한 피처의 평균을 빼고 분산으로 나눈다.
  • 그래서 분산 스케일링이라고도 부름
  • 스케일링된 피처의 결과는 평균이 0, 분산이 1
  • 즉 0을 중심으로 좌우로 적절히 데이터를 배치한다.

l2 정규화

  • 원본 피처 값을 유클리드 노름(norm)으로 불리는 l2 노름으로 정규화한다.(나눈다)
  • 원본 값 / (모든 데이터에 제곱을 한 뒤, 이를 모두 더하고, 다시 제급근(루트)를 씌워 준다.)
  • 자세한건 나도 모르니깐 통과.
  • 이상과 같은 피처스케일링은, 피처의 분포의 모양을 바꾸지는 않는다. 다만 분포에 대한 스케일만 변경한다.
  • 예를들면 원본 데이터를 이용해서 만든 그래프와, min-max를 이용해서 만들어진 그래프의 모양은 동일하다. 다만, 피처의 스케일만 달라져 있는 것이다.
  • 입력 피처들의 기준이 다를때는 비슷하게 만들어 주는것이 좋다. 방문자 수가 100만명 단위인데, 구매자 수가 100명 단위라면, 균형을 맞춰줄 필요가 있다.
  • 그렇지 않으면 모델 학습 알고리즘에서 수치 안정성 문제를 일으킬 수 있다.

상호작용 피처

  • 한개의 피처만을 사용하는것이 아니라, 두개의 피처를 모두 사용하는 방법.
  • 예를들면, "서울"에서 "30대" 같은것.
  • 고객의 위치만으로 예측하는것, 혹은 고객의 나이만으로 예측하는것 보다는, 둘 다의 값으로 예측하는것이 더 정확
  • 하지만, 더 복잡한 계산이 필요. 어떤 피처들 선택할 것인가도 문제.

피처 선택

  • 필요 없는 피처는 제거하는것이 모델의 복잡성을 줄일 수 있음.
  • 그러면 정확도는 거의 저하시키지 않고, 빠르게 연산 할 수 있을 것임.
  • 어느 피처가 중요한지 알아 내기 위해서, 오히려 전체 학습 시간이 오래 걸릴 수도 있음.

필터링

  • 피처와 목표 변수 사이의 상관관계, 상호 정보량등을 계산해 크게 영향을 미치지 않는것을 걍 제거.
  • 쉽게 할 수 있지만, 내가 필터링 할 피처를 잘못 선택할 수도 있다.
  • 아예 해당 데이터를 사용하지 않을 것이므로, 유용한 필터를 제거 할 수 있으므로, 보수적으로 선택해야 한다.

레퍼메소드

  • 비용은 많이 들지만, 피처의 하위 집합을 시험해 볼 수 있도록 해 줌.
  • 정보량이 많지 않을 수도 있지만, 조합했을 경우 유용한 것일 수 있으므로 실수를 방지 해 줌.

내장 메소드

  • 모델 학습 과정의 일부로서 피처 선택을 수행
  • 의사결정트리는 각 학습 단계에서 트리를 분할하기 위한 피처를 선택하게 되어 있음.
  • 선형 모델 학습에 사용하는 l1 정규화도, 모델 학습 과정의 일부로 피처를 선택하게 되어 있음.
  • 레퍼메소드 방식보다 강력하지 않지만, 비용이 절감
  • 필터링과 비교 했을 때 보다는 모델에 적합한 피쳐를 선택,
  • 필터링과, 내장 메소드 사이의 적절한 균현을 이룸
  • 이 책의 설명 범위가 벗어난다면서, 여기에 대한 설명을 다른곳을 찾아 보라고 함.

요약

  • 일반적인 숫자 피처에 대한 피처 엔지니어링을 설명
  • 통계적인 머신러닝에서 모든 데이터는 결국 숫자 피처로 귀결
  • 결국 몇가지 숫자 피처 엔지니어링 기법이 필요

3장 텍스트 데이터: 플래트닝, 필터링, 청킹

  • 문장이 있다면, 어느 부분을 추출해야 하나?
  • 단어 카운트 총계를 기초로 하는 가장 단순한 표현인 BoW
  • 텍스트와 매우 깊은 연관이 있는 변환 tf-idf

bag-of-x: 자연어 텍스트를 평면 벡터로 변환

  • 결과가 단순하고 해석 가능할때가 가장 좋음, 단순해야 시도해 보기 좋고, 디버깅이 쉽다.
  • 우선 단순하게 시작하고, 필요한 경우 복잡성을 더하도록 하자.
  • 문서를 분류하는 작업은 종종 단어 카운트 통계만으로도 충분함.
  • 특정 단어의 존재 유무가 문서의 주제를 잘 나타내는 지표가 됨.

BoW

  • Bag of word
  • 단어별 단어가 노출되는 갯수를 테이블로 만든것.
  • 이러한 단어별 카운트의 분포에 따라서 문서가 어떠한 특징을 가지는지 알 수 있다.
  • 텍스트는 원래 플랫(flat)한 구조이나, BoW는 단어가 몇번 나오는지만 저장해 둔다.
  • 텍스트는 순서(Sequance)를 가지나, BoW는 순서도 없다. 단어별 계층 구조도 없다.
  • 오직 등장한 횟수만...
  • 이렇게 단어와 등장 횟수를 피처를 만들고, 어떠한 문장을 분석해 보도록 하자.
  • 각 단어가 1개의 차원이 된다. 등장 횟수가 해당 피처의 값이 된다.
    • 특정 문장에서 cute라는 단어와 puppy라는 단어가 각각 몇번 나왔는지를 x, y로 두면 그 문장이 2차원의 어느 위치에 있는지 알 수 있다.
    • 특정 문장에서 cute, puppy, extremely 이라는 단어가 각 몇 번 나왔는지를 x, y, z로 두면 그 문장이 3차원에서 어느 위치에 있는지 알 수 있다.
    • 각 단어와 등장한 횟수가 피처가 되고, 문장이 어느 위치에 있는지 알 수 있다.
  • 반대로 각 문장 자체를 피처로 두고, 단어들을 배치해 볼 수도 있을 것이다. 이러한 것은 bag-of-documents 라고 한다. ( 자세한건 4장에 설명 된다고... )
  • BoW는 문장을 단어로 분해 할 때 의미가 파괴 될 수 있다. not bad의 경우 '나쁘지 않다.'라는 뜻인데, 분해를 해 버리면 둘다 나쁘다라는 의미를 표현하게 된다.
  • 이러한 문제를 일부 해결 하기 위해 bag-of-n-grams를 사용한다.
  • BoW는 유용한 경험적 방법이지만, 텍스트의 정확한 의미를 파악하는것과는 거리가 멀다.

bag-of-n-grams

  • BoW는 단어 당 하는건데, 여기는 n개의 연속된 단어로 하는거다. 1개로 되어 있으면, 1-gram, unigram 이다.
  • 중첩된 시퀀스를 n-gram이라고...
  • "Emma knocked on the door'를 2-gram으로 나타내면
    • Emma knocked
    • knocked on
    • on the
    • the door
  • 로 나타낼 수 있다.
  • 하지만 당연히 BoW 보다 훨씬 더 많은 피처 갯수가 생긴다.

정제된 피처를 위한 필터링

  • 단어를 사용할 때는 필요한 정보(시그널)과 노이즈(필요 없는 정보)를 분리해야 함.

불용어

  • 분류와 검색은 텍스트이 대한 깊은 이해를 요구하지 않음(의미까지 명확하게 파악하지 않아도 된다는 뜻일까?)
  • 분류와 같은 섬세하지 않은 작업에서 대명사, 관사, 전치사의 가치는 그다지 크지 않다.
  • 하지만 섬세한 의미론적 이해를 요구하는 감성 분석에서는 매우 다를 수 있다.
  • 영어의 불용어 리스트는, 파이썬 NLP 패키지인 NLTK에 수 많은 언어에 대해 불용어 리스트를 가지고 있다.

빈도 기반 필터링

  • 얼마나 단어가 나오는지를 확인하면, 상용어를 필터링 하기 쉽다.
  • 빈출 단어
    • 또한 단어가 너무 많이 나와도 의미를 파악하기 어려울 수 있다.
    • 의사 회의록은 'House of Commons(하원)'이라는 단어가 많이 나와서 house라는 단어가 너무 많이 나옴.
    • 이를 어떻게 처리 할 것인가를 정하는게 어렵다. 또한 얼마나 많이 등장 할 때만 의미를 부여/제거 할 것인가? 를 정하는것도 쉽지는 않다.
  • 희귀 단어
    • 잘 알려있지 않은 단어거나, 철자가 틀린 것일 수도 있음.
    • 통계적인 모델에서는, 한 두번 나오는건 잡음(노이즈-noise)에 가깝다.
    • 아주 적은 횟수가 등장하는 단어 때문에, 분류를 잘못 할 수도 있다.
    • 또한, 이러한 단어들을 모두 포함해서 연산을 하게 되면 필요 없는 계산을 많이 해야 한다.
    • 책에서 설명하는 Yelp 데이터 160만개 리뷰는 35만개의 고유 단어가 포함되어 있고, 약 23만개의 단어가 1개 혹은 2개의 리뷰에서만 나온다. 즉, 60%의 단어가 크게 의미를 가지지 않을 수도 있다는 뜻이다.
    • 이러한 피처를 모두 모델을 만들때 추가하게 되면, 계산 비용과 저장 비용이 많이 들게 된다. 그러므로 이러한 단어들을 적절히 제거해 주어야 한다.
    • 텍스트의 문장이 매우 짧은 경우, 통계적 의미를 찾기 어려울 수 있기 때문에, 이러한 문장을 제외해야 할 수도 있다. 하지만 트위터는 짧은 문장만을 가질 수 있으므로, 다른 방식의 기법을 사용해야 한다.
  • 어간 추출
    • 어간(語幹) : 활용어의 활용에서 변하지 않는 부분. '읽는다, 읽느냐, 읽고…' 등에서의 '읽'. 어간에 어미 '-다'를 붙인 것을 기본형이라고 하여 사전의 표제어로 올림. 줄기.
    • 단어를 공백이나 구둣점으로 잘라서 세면, 같은 의미를 가진 단어를 모두 따로 카운트 하게 된다. 'swin', 'swinging'은 의미가 비슷하지만 서로 다르다고 카운트 된다.
    • 통계적인 데이터로 처리 할 때에는 어간(stem)을 추출해서 단어의 기본형으로 변환하여 저장하는것이 좋은 경우가 많다.
    • 하지만, news 와 new는 전혀 다른 의미를 가지지만, 같은 new로 어간 추출이 될 수도 있다. 그러므로 항상 어간 추출을 사용해야 한다는것은 아님을 명심하자.

의미의 단위: n-grams에서 구문까지

파싱과 토큰화

  • 문자열에 의미가 있는 텍스트가 아닌게 많다.
  • 또한, 의미를 구분해 주는것도 있을 것이다. 이메일의 from, to 등.
  • 단어를 쪼갤때, 공백, 구둣점 등으로 나누면 된다.
  • n-grams으로 n개를 쪼갤때는, 문서가 아니라 "문장" 단위로 되어야 한다.
  • 즉, 마침표가 있으면 n-grams를 늘리면 안된다.
  • 하지만, word2vec 과 같이 복잡한 것을 할 때는, 단락에 적용할 수도 있다.
  • 암튼, 그냥 상황에 따라서 잘 나눠서 하면 된다는것 같다.

구문 탐색을 위한 연어 추출

  • 연어. 연달아 적힌 단어가 의미를 가질 수 있다.
  • strong tea는 "진한 차" 인데, 두 단어를 쪼개면, "물리력이 강하다"와 "차"로 나눠진다. 그러므로 의미가 달라진다. 이러한것을 연어라고 한다.
  • 'cute puppy'는 'cute'와 'puppy'의 의미를 합쳤을때 동일한 의미를 가진다. 이런건 연어가 아님.
  • 연어가 꼭 연속되어 나오라는 법도 없고, 모든 연속된 단어가 연어라는 법도 없다.
  • 그래서 너무 어려움. 통계적인 기법을 사용한다.
빈도 기반 방법
  • 많이 나타나는 n-grams을 보는 법. bigrams등의 빈도수를 실제로 확인해 보고, 의미 있는것을 찾을 수 있다.
연어 추출을 위한 가설 검증
  • 책에 나오는 복잡한 내용은 생략...
청킹과 품사 태깅
  • 주제를 찾는 경우에는 명사에 가장 관심이 있을 수 있음.
  • 즉, 품사를 찾아야 함.
  • 걍 형태소 분석을 한다는것으로 보인다. 통과. ㅋㅋㅋ

요약

  • Bag of Word
    • BoW, 단어를 하나씩 Bag에 넣는것
    • 단순 검색에는 좋으나, 문맥이 유지 되지 않아 의미를 파악하기 어려움
  • Bag of n grams
    • n-gram을 Bag에 넣는것, 연속된 단어를 n개 조합해서 저장
    • 하지만 연속된 단어 n개의 조합이 너무 많아서 데이터 양이 너무 많음
    • 데이터 양이 많다면, 의미를 가지는 데이터를 더 찾기 어려울 수 있다.
  • 연어(구문, 상용구) 추출
    • 연속된 구문을 보고 의미가 있고, 없는 것들을 통계적으로 추출할 수 있다.
  • 이 장에서 설명한 문장을 처리하는 방법은, 문장을 쪼개 단어의 bag으로 만들게 된다. 그러므로 이러한 방식으로는 문장의 의미를 구체적으로 파악하기는 어렵다.

4장 피처 스케일링의 효과: BoW에서 tf-idf로

  • BoW 는 필요 없는 단어들이 강조 될 수 있다. "is", "the", "and" 는 문장에서 너무 많이 나올 것이다.
  • 하지만, 문장에서 "happy", "gloomy" 등은 자주 등장하지는 않지만, 문장의 의미를 잘 표현한다. 이러한 것들을 잘 찾아 주는 방법을 찾아야 한다.

tf-idf: BoW 비틀기

  • tf-idf : term frequency-inverse document frequency
  • tf-idf : 용어 빈도 - 역 문서 빈도
    • 각 단어의 카운트를 해당 단어가 나타나는 문서의 수로 나눈 정규화 카운트
    • (하나의 문서에서 해당 단어 카운트)*log((전체 문서 수)/(해당 단어가 나타나는 문서의 수))
    • 전체 문서가 5개 일때, 모든 문서에 'is'가 들어간다고 하면 위 공식의 뒷 부분이 log(5/5) = log(1) = 0이다. 그러므로 위의 공식의 결과는 0 이다.
    • 'is'는 tf-idf 를 이용해서 처리하면 0이 된다. 즉, 모든 문서에 나오는 단어의 의미를 제거할 수 있다.

tf-idf 테스트

  • 자세한 내용은 생략
  • 학습을 시킬때, 데이터 카테고리별 갯수가 차이가 많이 나면 당연히 결과가 좋지 않을 것이다. 그러므로 데이터 카테고리별 갯수를 세고, 작은 쪽에 맞춰 주어야 한다.
  • 테스트셋에 트레이닝셋에 존재하지 않는 정보가 있다면, 당연히 테스트셋의 결과를 제대로 확인 할 수 없을 것이다.
  • 충분히 많은 양의 데이터라면, 테스트셋에만 존재하는 데이터는 "희귀"한 데이터 일 수도 있다. 그러므로 이때는 "그냥 무시"하는 방법을 써도 되는지 검토해 볼 필요가 있다.
  • 이 장에는... 머신러닝 관련되는 이런저런 이야기가 나온다. 난 걍 통과.

심층 분석: 무슨 일이 일어나고 있는가?

  • 생략

요약

  • 피처 스케일링을 통해 정보가 많은 단어는 강조되고, 상용어는 가중치가 낮아진다.

5장 범주형 변수: 로봇닭 시대에 달걀 개수 세기

  • 범주형 변수(categorycal variable)
  • 카테고리나 레이블(label)을 나타내는 방법
  • 범주형인지 아닌지 알아 내는건 쉬움. 연속적인지 아닌지를 판단하면 됨.
    • 주가 10달러와 15달러는 연속적인 값.
    • "정치", "경제", "사회"는 연속적이지 않은 값.
  • 문서 코퍼스(corpus)의 어휘도 각 단어가 구분되므로 커다란 범주형이라고 볼 수 있음.
  • 하지만 같은 단어가 여러번 나타날 수도 있으니, 이를 카운팅 할 수 있음.

범주형 변수 인코딩

  • 범주는 일반적으로 숫자가 아님. 예를 들면 "빨간색","검은색","파란색" 등이다.
  • 제일 쉬운 방법은 숫자를 1씩 증가시키면서 매길 수 있을 거다. 하지만, 이렇게 하면 값의 크기가 의미가 생길 수 있다. 그러므로 다른 방법을 찾아 보자.

원-핫 인코딩

  • 00001000, 1000000, 00100000 와 같이 여러개 중에 한개만 켜지는거(아니깐 생략)

더미 코딩

  • 원-핫 인코딩은 1개는 무조건 1이어야 하나, 더미 코딩은 모두 0 인게 있음.
  • 모두 0 인게 기준 범주.(기준 범주와 다른 애들과의 차이를 쉽게 볼 수 있다.)

이펙트 코딩

  • 더미 코딩의 모두 0 인것이, 모두 -1로 되는 것
  • 뭔 말인지 모르겠으니깐 통과. ㅎ.

범주형 변수 인코딩의 장단점

  • 원-핫 인코딩, 더미 코딩, 이펙트 코딩의 처리 방법은, 범주의 수가 매우 커지면 성능이 급격히 떨어진다. 수가 매우 많은 범주형 변수를 처리하기 위해서는 또 다른 전략 필요.

대규모 범주형 변수 처리

  • 피처 해싱 : 문자열, 숫자등을 해싱해서 변환, 매핑. 단점 : 원본 피처에 대한 정보가 사라져 더 이상 해석하기 어려워짐.
  • 빈 카운팅 : 어려우니깐 생략

요약

  • 책에 잘 정리 되어 있으니, 책 참고.

6장 차원 축소: PCA로 데이터 패케이크 납잡하게 만들기

  • 주성분 분석(PCA, Principal Component Analysis), 피처 차원 축소
  • 어려운건 다 생략하고...

직관

  • 차원 축소 : 핵심 정보는 유지하면서, '쓸모없는 정보'를 제거하기 위한 것
  • 수학적으로 새로운 피처 공간에서 데이터포인트들의 분산이 최대로 되게 한다.

수식 유도

  • 생략

PCA의 활약

  • MNIST 데이터중 8x8 로되어 있는 저해상도 데이터는, 64차원의 데이터를 갖는다.
  • pca_tranformer = PCA(n_componets=0.8)로 하면, 전체 분산의 최소 80%를 설명하는 수준에서 자동 선택.
  • 화면에 출력 결과, 3차원의 데이터만으로 비슷한 숫자들을 가깝게 그룹지은것을 볼 수 있음.

화이트닝과 ZCA

  • 모르겠으니깐 생략.

PCA의 고려사항과 한계

  • 차원 축소를 위해 PCA를 사용할 때는 얼마나 많은 주성분(k)을 사용할 것인지를 확인해야 한다.
  • PCA는 변환이 매우 복잡함. 결과 또한 해석이 어려움. 계산 비용도 많이 듬. 데이터 포인트나 피처의 수가 매우 많다면 수행하지 않는것이 좋다.
  • 데이터가 스트리밍으로 들어오면 PCA를 수행하기 어려움 ( 지금까지의 값으로 분산이 크도록 해 두었는데, 새로 들어온 값이 그것을 깰 수도 있다. )
  • 카운트에 사용하지 않는것이 좋다. 이상치(아웃라이어)들이 있기 때문에, 상관 관계가 쉽게 깨질 수 있다. 사용하고 싶다면, log등을 사용해서 처리하는 방법을 찾거나 하면 된다.

사용 예

  • PCA 변환은 데이터에서 정보를 제거한다. 따라서 이 정보로 모델을 학습할 때는 계산 비용이 적게 들지만, 정확도는 떨어질 수 있다.
  • PCA를 사용한 멋진 애플리케이션 : 시계열 데이터의 이상 탐지, 재무 모델링, 주가의 상관관계 패턴...(모르겠음 ㅋ )

요약

  • PCA에 대해 기억해야 할 두가지 핵심
    • 메커니즘 : 선형 투영
    • 목표 : 투영된 데이터의 분산 최대화
  • PCA는 모델 중심 피처 엔지니어링의 한 예. 분산이 데이터가 가지고 있는 정보를 적절하게 표현한다는것.
  • PCA는 잘 알려진 차원 축소 기법. 하지만 큰 계산 비용이 들고 결과물을 해석할 수 없다는 제약.
  • PCA 특히 피처들 사이의 선형 상관관계가 있을 때 전처리 단계로써 유용.

7장 k-평균 모델 스태킹을 통한 비선형 피처 생성

  • PCA는 데이터가 평평한 팬케이크 모양의 선형 부분 공간에 있을때 유용
  • 데이터가 휘어진 곡면으로 이뤄진(스위스 롤 같은) 경우. 결국은 2D 평면이 둥글레 말려 3D로 된 것임.
  • 피처 엔지니어링의 목적은 피처의 차원을 낮게 만드는것이 목적이 아니라, 과제를 수행하기 적합한 피처를 얻는 것
  • 가까이 있는것들을 모으는 클러스터링 방법을 사용할 수 있다.
  • 클러스터의 수가 원래의 피처 수 보다 작으면, 차원이 축소 되었다고 볼 수 있다.

k-평균 클러스터링

  • 비슷한 공간상에 놓여진 데이터를 그룹화 하는것.
  • 비지도 학습
  • 유클리드 기하학으로 두 점 사이의 거리를 측정 하여 근접성을 측정한다.
  • k-평균은 각 데이터 포인트가 오직 하나의 클러스터에만 할당되는 하드 클러스터링
    from sklearn.cluster import KMeans
    # 10개의 클러스터로 나눈다.
    clusters = KMeans(n_clusters=10, ramdom_state=1).fit_predict(numpy_array);

곡면 분할로서의 클러스터링

  • 스위스 롤 형태의 데이터를 KMeans 클러스터링으로 할때 k가 너무 작으면 클러스터가 잘 나눠지지 않는다.

분류를 위한 k-평균 피처 생성

  • 목표 변수를 사용하면, 그 값을 기준으로 클러스터링을 할 수 있다.(?)
  • 생략

장단점과 몇 가지 사항들

  • 생략

8장 피처 생성 자동화: 이미지 피처 추출과 딥러닝

  • 예전 방식에 대한 설명과, 딥러닝에 대한 설명을 모두 진행

가장 단순한 이미지 피처(그리고 이것이 동작하지 않는 이유)

  • 이미지를 검색하려고 한다마녀, 이미지 데이터 베이스에서 비슷한 이미지를 찾아야 한다.
  • 단순히 이미지에 있는 개별 픽셀 색상 값을 가지고 처리 할 수 없음. 이미지 간의 차이를 어떻게 계산 할 것인지를 결정하는것이 핵심

수동 피처 추출: SIFT와 HOG

  • 이미지 그래디언트(인접픽셀과의 차이)를 활용해서 벡터를 구한다.
  • ... 생략 ...

심층 신경망으로 이미지 피처 학습

  • Fully Connected Network, Convolution, ReLU, Normalization, Max Pooling 설명
  • AlexNet 설명
  • 이 분야에서의 엄청난 발전에도 불구하고 이미지 피처 생성은 아직 과학보다는 예술에 가깝다.
  • 10년 전에 사람들은 이미지 그래디언트, 테두리 탐지, 방향 탐지, 공간 단서, 스무딩, 정규화 등을 사용해 피처 추출을 수작업으로 진행했다.
  • 요즘은 딥러닝 아키텍트가 동일한 아이디어를 캡슐화 하는 모델을 작성하기는 하지만, 파라미터들은 학습용 이미지를 통해 자동으로 학습된다. 마법은 여전히 존재하며, 단지 모델의 더 깊숙한 곳에 추상화돼 숨어있을 뿐이다.

9장 다시 피처로: 학술 논문 추천 시스템 구축

  • 실제 예제를 사용해서 데이터 피처링을 해 보자

항목 기반 협업 필터링

  • 생략

첫 번째 단계: 데이터 가져오기, 정제하기, 피처 파싱하기

  • 단순 두 개의 피처만 사용해서 항목 유사도(코사인유사도)를 구했는데. 시간이 엄청 오래 걸렸다.
  • 데이터 갯수가 너무 많으니 계산하는데 시간이 너무 오래 걸림.
  • 현재의 방식은 반복적인 엔지니어링을 위해서 너무 느리다.

두 번째 단계: 피처 엔지니어링과 더 똑똑한 모델

  • 출간년도를 비닝으로 처리. 10년 단위로 비닝을 해서 피처 공간을 156에서 19로 줄임.
  • 데이터 프레임을 희소 배열로 변환
  • 위와 같이 하면 누락된 데이터가 매우 많을 것이다. 더 많은 정보를 가진 피처를 선택할 수 있는지 살펴 봐야 한다.

세 번째 단계: 추가 피처 = 추가 정보

  • 기존의 피처에서 추가로 초록(abstract)과 저자(authors)를 추가 할 수 있음
  • 초록(abstract)이나 제목의 경우 명사구나 stem(어근)을 구해서 처리 할 수도 있다.

+ Recent posts