[혀로그래머 charsyam은 구라쟁이 Q&A] 레디스 관련 Q&A

안녕하세요. 혀로그래머 구라쟁이 charsyam 입니다. 오늘은 제가 자주 서식하는 페북 커뮤니티에 질문을 누군가 올려주셔서 거기에 대한 답변을 간단하게 달아놓은 것을… 질문이 워낙 좋으셔서… 정리해 봤습니다.

먼저 질문은 다음과 같습니다.

  1. 인프라 구조에서 Scale-Out 구조를 가진 경우 각 데이터를 어떤 Node에 저장되고 있는지를 판별하고 있어야 하며 데이터 유실을 대비하여 데이터 블럭을 보통 분리하여 저장합니다. 레디스의 경우 한 노드가 죽었을때 휘발성인 캐쉬임을 대비하여 어떤 방식을 구현하는지요?
  2. 본문에 사용량이 많아지면 메모리 파편화가 일어난다고 하였는데(보통 디스크나 메모리의 경우 영속성이 있어야 성능이 잘나오는걸로 알고 있습니다.) 해당 파편화를 줄이는 알고리즘이나 파편화가 일어난 경우 해당 데이터를 재배치를 하는건가요?
  3. 서버 아키텍처는 캐쉬의 경우 여러 종류의 캐쉬를 두어 각 캐쉬별 역할을 구분하게 되어지는데 레디스도 그런 방식을 차용하고 있는건가요?
  4. 이슈를 대비하여 서버 대수만 늘려야한다면 아키 설계가 어려울듯 한데 아키 설계는 보통 어떻게?
  5. 레디스 서버 한대 다운시 처리는 어케 하는지요

여기에 대한 답변을 다음과 같이 정리했습니다.

  1. 인프라 구조에서 Scale-Out 구조를 가진 경우 각 데이터를 어떤 Node에 저장되고 있는지를 판별하고 있어야 하며 데이터 유실을 대비하여 데이터 블럭을 보통 분리하여 저장합니다. 레디스의 경우 한 노드가 죽었을때 휘발성인 캐쉬임을 대비하여 어떤 방식을 구현하는지요?
    1. 글에서 언급한 것 처럼 그냥 버리는 케이스가 있습니다. 각 노드들에 데이터들이 날아가도 실제 DB에서 처리할 수 있는 정도라면… 예를 들어 한대 죽었을 때 10% 정도 부하가 올라가는데, 이 정도는 원래 처리할 수 있다면, 무시해도 되겠죠.
    2. 캐시도 중요할 경우 Master/Slave 로 레디스 같은 경우 설정해 둘 수 있습니다. 멤캐시는 이게 안되서, 따로 리플리케이션을 구현하셔야 합니다.(Mysql Binlog를 이용하든지, 서버 로직에서 두 군데를 쓰든지…)
  2. 본문에 사용량이 많아지면 메모리 파편화가 일어난다고 하였는데(보통 디스크나 메모리의 경우 영속성이 있어야 성능이 잘나오는걸로 알고 있습니다.) 해당 파편화를 줄이는 알고리즘이나 파편화가 일어난 경우 해당 데이터를 재배치를 하는건가요?
    1. 레디스의 메모리 파편화는 다른 장비로 이전하는 수 밖에 없습니다. 보통 메모리 파편화가, 잦은 메모리 할당과 해제로 인해서 발생하므로, 장비 이전을 하면, 삽입만 대량으로 발생하니, 단편화 이슈가 조금 덜합니다. 보통 이런 경우 메모리를 2배로 늘린 장비로 이전합니다. 이전 과정은 간단하지만, 모니터링이 필요합니다.
    2. 말씀하신것 처럼 해당 데이터를 재배치 하는 것은 현재 레디스 상황에서는 쉽지는 않습니다. 재배치를 해봐도, 메모리 상황이 바로 좋아지는 것이 아니라, jemalloc에서 내부적으로 관리하는 매커니즘과 섞여서, 좀 외부에서 알기 어렵습니다.
  3. 서버 아키텍처는 캐쉬의 경우 여러 종류의 캐쉬를 두어 각 캐쉬별 역할을 구분하게 되어지는데 레디스도 그런 방식을 차용하고 있는건가요?
    1. 레디스가 내부적으로 그렇게 나누는 것은 아니고, 캐시를 사용하는 비지니스 로직에서 보통은 종류를 나눠서 사용하는 것이 제 경험상 메모리 사용량이나 파편화면에서 유리했습니다.(보통 그렇게 많이 쓰구요.)
    2. 통합 캐시(그냥 다 때려박는 형태)의 경우는 아이템별 메모리 사이즈의 차이가 커서 파편화를 더 가속화 시키는 측면이 있습니다.
  4. 이슈를 대비하여 서버 대수만 늘려야한다면 아키 설계가 어려울듯 한데 아키 설계는 보통 어떻게?
    1. 클라우드냐, 자체 IDC냐에 따라서 고려해야 할 것들이 좀 바뀝니다. 일단, 공통적으로 서비스의 Configuration이 Dynamic 할 수 있어야 합니다. 뭘 쓰는지는 크게 중요하지 않지만, 서비스를 내리고 올리는 형태가 아니라, 특정 보드에 설정을 바꾸면, 그게 전체 서버에 자동으로 반영되서, 서비스를 중단하지 않을 수 있어야 합니다. 서버의 추가나 제거도 마찬가지 입니다.
    2. 그런 아키텍처가 구성이 되면, 이제 IDC냐 클라우드냐에 따라서 고민할 것이 네트웍 밴드위스와 상면의 이슈가 있습니다. 개발자 입장에서는 네트웍 스위치의 밴드위스를 고려하지 않는 경우가 있는데, 이럴 경우, 큰 문제를 일으킬 수 있습니다. 상면 위치도 마찬가지입니다. 미리 잘 고민 안하면, 장비가 추가가 안되서, 해당 캐시만 다른 IDC에 넣어야 하는 경우도…(레이턴시가…)
  5. 레디스 서버 한대 다운시 처리는 어케 하는지요
    1. 레디스 서버 한대 다운시는… 여러 가지 방법이 있습니다. 자동 failover를 원하시면 sentinel 을 쓰든지 자체로 간단한 agent 를 만들어서 하는 방법이 있습니다. 이걸 vip, dynamic dns랑 잘 활요하면 클라이언트 입장에서는 크게 신경을 쓰지 않게 auto failover 를 제공할 수도 있습니다.
Advertisements

[혀로그래머 charsyam은 구라쟁이 #2] 캐시 멤캐시나 레디스 쓰세요. 쉬워요

안녕하세요. 혀로그래머이자 구라쟁이 charsyam 입니다. 오늘은 지난 1편 [혀로그래머 charsyam은 구라쟁이 #1] 샤딩은 쉬워요 샤딩하세요. 의 뒤를 이은 2편 “캐시 멤캐시나 레디스 쓰세요. 쉬워요” 편입니다.

일단 캐시를 왜 쓰는걸까요? 캐시라는 의미는 원래는 연산이 오래 걸리는 작업이나, 레이턴시가 긴곳에서 뭔가 가져와야 할때, 그 시간을 위해서 보다 빠른 저장 장치나, 미리 결과를 저장해 놓고 전달하는 것을 말합니다.

즉, DB나 다른 API 서버에서 결과를 받아와야 하는 것이 느리면, 메모리나, 로컬에 미리 저장을 해놓고 그 결과를 던져주는 것으로 시간을 줄이는게 캐시의 역할입니다.

그런데 로컬에만 들고 있으면, 어떤 서버는 해당 값을 들고 있을 수도 있고, 또 어떤 서버는 없을 수도 있고, write가 발생하면 해당 캐시를 지워줘야 하는데…, 그럼 전체 서버에 해당 값을 지우라고 보내야 하니깐… 귀찮아서, 어느 서버에 데이터를 담아두고, 모두가 거기를 참조하게 됩니다.

이때, 보통 멤캐시나 레디스를 쓰게 됩니다. 남들이 많이 쓰니깐, 추천도 많이 받으니깐요. 현재는 보통 멤캐시보다 레디스를 더 많이 사용하게 됩니다. 이 이유를 설명하자면 복잡한데, 간단하게 설명하면, 레디스가 더 많은 기능을 제공해 줍니다. 그래서 사용하기에 더 편합니다.(레디스 말고 캐시로만 쓰실꺼면 Memcache 변형인 Arcus 같은 것도 좋습니다.)

사실, 이런 캐시가 도입되면 사실 여러가지로 편해집니다. 속도도 빨라지고, 알고리즘이 기본적으로 제공되는 것들을 이용하면, 구현도 좀 더 쉬워지고요. 실제로 거의 대부분(99.99999%) 의 웹서비스 업체에서는 멤캐시나, 레디스를 이용하고 있습니다. 아래를 보면 DB 앞에 멤캐시를 추가하고 나서 DB의 query 가 변경되는 실제 예입니다. select query 수가 1000 까지 오르던 것이 거의 100 근처까지 떨어진 것을 알 수 있습니다.

스크린샷 2017-05-28 오전 12.49.08.png

 

레디스나 멤캐시를 쓰다보면, 처음에는 모든 것이 좋습니다. 그래서 이런 글도 있습니다.

레디스와 함께한 시간 모두 눈부셨다.

날이 좋아서

날이 좋지 않아서

날이 적당해서

모든 날이 좋았다.

(드라마 레디스)

그런데 트래픽이 몰아치고,  메모리가 한계에 이르기 시작하면 새로운 세상이 펼쳐집니다. 보통 말하지 않는 것들이 모두 이 메모리의 이슈와 연관되어 있습니다.

먼저 첫번째 문제로, 캐시가 죽으면 어떻게 해야 할까요? 캐시니깐 죽어도 됩니다라고 말하면, 구라입니다. 트래픽이 적을 때는 큰 문제는 아닙니다. 자, 캐시가 무엇때문에 쓴다고 했었나요? 연산이 오래걸리거나, 시간이 긴 작업의 속도를 빠르게 제공하기 위해서 입니다. 그럼 다음과 같은 상황을 가정해봅시다.

  1. 현재 트래픽이 굉장히 높습니다.
  2. 캐시가 죽습니다.

그러면, 이제 기존의 트래픽이 어디로 가게될까요? 빙고, DB로 가게 됩니다.(사실입니까?) 그럼, 캐시가 전혀 없을 때, 이 DB가 버틸 수 있다면, 사실 큰 문제가 없습니다.(아깐 앞에선 구라라며, 여기서도 구라를…) 그런데 보통 캐시가 대부분의 처리를 담당하고 있었다면, 캐시 서버가 죽는 순간 모든 트래픽은 DB로 전달되고, DB가 못버티면, 서비스 장애가 발생하게 됩니다. 그러면 캐시 서버는 몇대를 두는 것이 정답일까요? 정답은…

 

정답은… 죽어도 디비에 큰 영향이 없을 수 만큼 두어야 합니다.(즉 케바케!!!, 죽어 퍽퍽퍽, 이런걸 답이라고…) 사실, 결국 이런건 적절히 서비스를 운영해보면서 바꿀 수 밖에 없습니다. 약간의 힌트가 있다면, 캐시 없이 버틸 수 있는 QPS가 어느정도인지 확인해보고, 캐시가 커버해주는 처리량등을 잘 확인해야 합니다.

그렇다면, 캐시 서버들이 죽지 않도록 만들면 되지 않을까요? 라는 질문을 할 수 있습니다. 그런데, 그러기 위해서 필요한 것들이 캐시 서버의 메모리 관리입니다. 그런데 이 메모리 관리가 쉽지가 않습니다. 특히 멤캐쉬의 경우는 좀 문제가 적은데, 레디스의 메모리 관리는 많은 노력이 필요합니다.

일단 레디스는 메모리 파편화가 발생하기 쉽습니다. 그로 인해서 항상 레디스의 RSS 실제 물리 메모리 사용량을 모니터링 하다가, 어느 수준의 증가가 보이면, 다른 장비로 이전을 시켜줘야 합니다. 그럼 이 과정은 쉽냐?, 크게 어렵지는 않지만, 또한 실패할 가능성도 있습니다. 그리고, 이를 위해서는 결국 서버 아키텍처가 이런 변화를 쉽게 대응할 수 있도록 해줘야 합니다. 다른 장비로 이전을 한다면, 기존 서버의 도메인이나 ip를 새로운 장비가 가지도록 하거나, 쉽게 시그널을 보내면, 기존 장비 대신에 새로운 서버로 연결되도록 미리 만들어 두어야 합니다.(하지만 실제로 이러기도 쉽지는 않습니다.)

또한 죽지 않더라도, 인메모리 캐시들은 스왑메모리 영역을 사용하게 되면, 그때부터 성능이 많이 떨어지게 되는데, 멤캐시나 레디스를 쓰다보면, 특정 상황에 스왑메모리를 사용하게 되는 경우가 발생합니다. 이렇게 되면 해당 캐시서비를 리스타트 하지 않는 이상 해당 메모리는 계속 스왑을 쓸 수도 있기 때문에, 특정 상황에서 성능이 저하될 수 있습니다.

 

정리하자면, 레디스나 멤캐시를 사용하는 것은, 쉽고 좋습니다. 하지만, 이를 많이 사용하게 되었을 때 부터의 관리 이슈는, 상당히 심각합니다. 이를 해결하지 못하면, 도리어 레디스나 멤캐시를 사용하는 것이 심각한 문제의 원인이 됩니다.

 

재밌는 것은 많이 쓰는 곳은 외국의 큰 회사들도 같은 문제를 가지고 있습니다. 1대, 2대가 아니라, 몇십대, 아니면 몇백대, 아니면 몇천대를 쓰는 곳에서는 이런 이슈들을 어떻게 다루어야 할까요? 거기에 대한 많은 고민이 필요합니다.

[혀로그래머 charsyam은 구라쟁이 #1] 샤딩은 쉬워요 샤딩하세요.

안녕하세요. 혀로그래머!!! charsyam 입니다.  민방위 훈련을 받다가, 나처럼 실력 없는 개발자는 스스로 갈궈야 한다라는 생각이 들어서, 스스로를 비판하고 까기 위한 글을 쓰기로 했습니다.

원래 제가 발표하는 주 대상이 주로 개발 경험이 많이 없는 학생, 주니어들을 대상으로 하다보니, 많은 구라를 포함하고 있습니다.(제가 발표때 마다 호구(?) 조사를 빙자해서 학력/경력을 물어보는 이유입니다.) 그 중에서 가장 대표적인 구라가 바로… 샤딩 쉬워요. 샤딩하세요 입니다.

사실 서비스가 성장해 나가다가 가장 문제가 되는 부분이 데이터의 폭발입니다. 서비스가 성장하는 데 API 서버가 문제라면 소위 Stateless 형태라면, 쉽게 확장이 가능합니다.(이런 얘기 할 때, 절대로, Stateless 하지 못한 경우는 언급하면 안됩니다. 구라가 깨집니다.) 그런데 데이터의 폭발로 인해서 DB서버가 늘어나야 한다고 하면, 뭔가 버거워 보입니다. 그래서 항상 서비스 시작 전에 이런 부분에 대해서 미리 고민하고 시작해라라고 말을 합니다.(딱, 여기까지만 얘기합니다.)

그러면서 화려하게 DB 샤딩 방법에는 Range, Module, Indexed 같은 방법이 있고, 각각의 특성이 있다고 하면서 섞어써도 된다는 말들을 화려하게 해줍니다. 이러면서 구라가 완성이 되는 거죠.

그런데…, 처음 서비스를 구축할 때 부터, 이런 부분을 고려하면 정말 좋은걸까요? 당연히 시간이 조금 더 걸립니다. 하지만, 뒤에는 좋긴 합니다. 처음부터 고려를 하고 시작한 서비스니깐요. 그리고 여기까지만 얘기하고 이제 조용히 종료를 해야죠.(구라는 언제나 진실과 함께 해야만  잘 먹혀듭니다.)

그런데, 이런 고민을 서비스를 시작할때만 할까요? 기존에 서비스를 쓰고 있던 업체들에게도 샤딩하세요 라고 얘기를 합니다.(실제로는 서비스하시는 분들은 제가 피해다닙니다. 구라가 걸릴까봐… 손목가지 날라갑니다.) 그런데 그게 그렇게 쉽게 가능할까요?

자, DB 한대, API 서버 한대로 운영중인 회사가 있다고 하겠습니다. 서비스가 성장하는게 보입니다. 이제 슬슬 DB 서버에 데이터가 꽉 찬거 처럼 보입니다. 그런데 지나가던 구라쟁이(?)가 샤딩하세요, 어렵지 않습니다. 이런 얘기를 합니다. 그걸 믿고, 이제 사장님은 개발자에게 샤딩을 하라고 시키시죠. 그거 쉽데, 이런 것들이 있고, 블라 블라 블라 하십니다.

아, 쉽겠구나 하면서, DB 로직을 살펴봅니다. 그런데… 어디서 join 문들이 보이기 시작하네요. 또 프로시저 같은것도 쓰고 있습니다. 슬슬 열불이 나기 시작합니다. 어떤 XX가 쉽다고 얘기했을까요?

잘 생각해보면 DB 서버 안에 테이블 여러개라면 join이 쉽게 가능합니다. 느리게 돌 수도 있지만, DB가 처리하는 것 만큼 효과적으로 짜기도 어렵습니다. 그런데… 샤딩을 하고 나니… 테이블이… 서로 다른 서버에 데이터를 나눠 가지고 있습니다. join 해야할 테이블도 분리되어 있습니다.

거기다가, 트랜잭션도 쓰고 있군요. 이제 부터 지옥이 펼쳐집니다. 사실 기술 세미나에서 이런 얘기를 쉽게 하지 않습니다. 사실 쉬운 방법도 없구요. 처음부터 시작하면서 이런걸 고민해도, 사실 쉽지 않을 수 있습니다. 다른 테이블 간의 트랜잭션도 없애야 하고, join도 다 로직단에서 처리를 해줘야 합니다. 처음 부터 그렇게 만들지 않았다면… 절대로 쉬운 일이 아닙니다. 이렇게 되면, 실제로 코드에 해당 실패에 대한 대응들이 다 들어가야 합니다. 일종의 보상 처리라고도 합니다만… 잘 짜도 실수의 여지는 항상 있습니다.(돈 많이 주고 오라클 쓰시는 방법도 있다고 합니다. 전 안써봐서 모릅니다.)

그럼 문제가 여기에만 있을까요? 아닙니다. 샤딩을 하면, 이제 장비가 추가되어야 할 때마다, 노력이 추가로 들어갑니다. 물론 어느정도 자동화가 가능합니다만, 꼭 모니터링이 필요한 일입니다. (이런 글을 참고하세요. http://gywn.net/2012/05/how_to_shard_big_data_in_tumblr/)

밑단의 데이터에서 뭔가 변경이 일어나는 것은 절대로 쉽지 않습니다. 다만 성장하다보면, 절대로 피해갈 수 없는 길이기도 합니다. 그리고 누가 샤딩이 쉽다라고 하면, 아 저 아재 구라쟁이구나 이렇게 보셔도 됩니다.(초천재일수도 있긴 합니다만…)

다음 편은, 캐시 멤캐시나 레디스 쓰세요. 쉬워요에 대한 구라를 파헤치도록 하겠습니다. 모두들 고운하루되세요.

[용어 정리] 입 개발자를 위한 TF-IDF

뭔가 아는척을 위해서 알아두면 좋은 단어중에 지난번에 언급했던 Accuracy, Recall, Precision 같은 것들이 있는데, 이것 말고도 알아두면 입 개발자로 아는 척 하기 좋은 단어가 있습니다. 바로 TF-IDF 인데요. 보통, 검색이나 다른쪽을 하시는 분들은 다들 잘 알고 있는 단어이기도 합니다.(개인적으로는 해당 강의 https://www.coursera.org/learn/ml-foundations 를 들으시길 추천합니다.)

그럼 일단 단어를 정리하면 TF-IDF 는 TF와 IDF의 합성어입니다.

TF Term Frequency, 문서에서 해당 단어가 얼마나 나왔는지를 나타내는 단어, 예를 들어,  이 문서에 “입개발”이 10번 나오면 입개발의 TF는 10이라고 할 수 있습니다. 다만 이런 값의 정의는 바꿀 수도 있습니다. 여러번 나와도 1이라고 정의할 수도 있고, 엄청 많은 값을 좀 줄이기 위해서 log 값을 씌우기도 합니다.
DF Document Frequency 입니다. TF는 한 문서에서 나타난 빈도라면, DF는 전체 문서들에서, 몇 개의 문서에 나타나는지에 대한 값입니다.  즉 이에 대한 수식은 대략 (해당 단어가 나타난 문서 수/ 전체 문서 수) 라고 보시면 됩니다.
IDF Inverse Docuemnt Frequency 입니다. DF의 역수를 취했다고 보시면 됩니다. 즉 (전체 문서 수/해당 단어가 나타난 문서 수) 입니다. 그런데 해당 단어가 있는 문서가 없을 수도 있으니 보통 분모에 1을 더해줘서(0 되지 말라고), 해서 (전체 문서 수/1 + 해당 단어가 나타난 문서 수)로 많이 표시합니다.

이제 여기서 중요한 것은 왜 IDF를 사용하는가 입니다. 검색이든, 문서의 유사도 검색을 할 때도 많이 사용하는데, 이런 것들을 할때 중요한 것은 해당 문서의 특징을 뽑아내는 거라고 할 수 있습니다.(지금부터 구라가 작열합니다!!)

먼저 문서의 유사도를 비교한다면 어떻게 할 수 있을까요? “머신러닝” 이렇게 외치시면, 일단 “러닝머신”을 한두시간 타 보시고요. 어려운 방법을 빼고 생각해보면… 단어가 얼마나 일치하는가 보면 될것 같습니다.

  1. 단어들을 모두 분리해서, 각 단어의 개수를 센다.
  2. 해당 단어들의 개수랑 얼마나 일치하는 지 살펴본다.
    1. 그런데 요 부분도 이해하기 어려울 수…

tfidf1

위의 그림을 보면 각 단어의 출현 빈도를 저장하고, 이 값들을 비교해서 다른 문서와 얼마나 유사한지 비교하게 됩니다.

tfidf2

위의 그림도 단순한 유사도를 구하는 예입니다. 여러 가지 방법이 있을 수 있습니다.(여기서는 문서에 많은 단어가 있으면, 그 유사도 값이 너무나 커버리는 이슈도 있어서, 이 값을 normalize 를 시켜야 하는데 이런건 일단 넘어가도록 하겠습니다. )

그런데 문서를 하나 본다면 일단 설명을 쉽게 하기 위해서 영어를 예로 들면, the, a, an, and, or, but 등등의 관사나 조사 같은 것들이 많이 들어있게 됩니다. 그런데 단순히 문서를 단어로만 나눠서 갯수로 비교를 한다면? 위의 기법을 써버리면 엄청 the 가 많아도 다들 비슷한 문서로 생각해 버리게 될겁니다. 그럼 어떤 방법이 있을까요? 간단하게 생각하기에…

  1. 저렇게 쓸모 없는 단어를 다 빼고 비교한다.
    1. 그럼에도 중요한 단어와 중요하지 않은 단어를 구분하지 못하는 문제가…
  2. 그냥 저렇게 중요하지 않을 단어들은 가중치를 낮게 주고 중요한 단어들은 가중치를 올려주자.

위의 두 방법중에, 1번은 꽤 명확한데, 2번은 그럼 중요한 단어를 어떻게 정할 것인가 하는 이슈가 생깁니다. 그런데 지금 이게 무슨 용어를 설명하는 걸까요? 네, 그렇습니다. TF-IDF!!!

즉, TF-IDF가 중요한 단어와 중요하지 않은 단어를 구분할 수 있는 방법인 것입니다. 여기서 일단 TF-IDF의 가정은, 특정 단어가, 해당 문서에서는 자주 출현하지만, 다른 문서에서는 많이 안나오면 중요한 단어일 것이다 라는 것입니다. 왜냐하면 다른 문서들에도 자주 나오는 거면, 아까 말한 the, a, an, of, and, or, but 같은 관사나 접속사등이 많을 것이기 때문입니다.

이제 뭔가 연관이 보이시나요? IDF의 (전체 문서 수/해당 단어가 나타난 문서 수)가 어떤 의미일까요? 즉 해당 단어가 적은 문서에 나타날 수록 IDF 가 커지게 됩니다. DF는 반대로, 해당 단어가 여러 문서에 나타날 수록 값이 커지는거구요.

이제 IDF를 구함으로써, 우리는 문서들 중에서는 적게 나타나는 단어를 찾을 수 있게 되었습니다. 그리고 해당 문서에서 중요한 단어는 TF로 구할 수 있기 때문에, 우리의 핵심 가정 – “해당 문서에서는 자주 나타나고, 전체 문서에는 적게 나타나는 단어”를 구하는 방법이 TF와 IDF를 곱하는 TF-IDF 가 되는 것입니다.

그런데 실제로 아까 제가 말한 공식으로 바로 쓰지는 않습니다. 왜냐하면 해당 값들이 천차 만별로 커지기 때문에, 로그를 씌운다든지, 제곱근을 구한다든지 그렇게 됩니다. 위키디피아에 꽤 설명이 잘 되어 있습니다. https://ko.wikipedia.org/wiki/TF-IDF

[용어 정리] 입개발자를 위한 Accuracy, Recall, Precision

최근에 공부하게 된 내용을 아주 가볍게 정리하고자 합니다. 머신러닝은 못하고 러닝머신도 못하고 있지만(저질 체력이라…) 맨날 공부하자 말만 하고 모르고 있다가… 아는 게 없어서 맨날 구라만 치는 중입니다. 그러던 중, 위의 내용들을 가볍게 설명할 일이 생겼는데… 역시 저의 구라로 시작한 일은 비극적으로 구라가 들통나버리는… 흑흑흑

그래서 좀 더 큰데서 구라를 다시 한번 치기 위해서 용어를 정리합니다. 흑흑흑 그래요 저 이런것도 모릅니다.

table

(해당 그림은 wikipedia 에서 가져왔습니다.)

다들 아시겠지만, 저는 잘 모르니… 먼저 간단하게 정리합니다. 일단 다음 4개의 용어를 먼저 기억해야 합니다.

True Positivie(TP) True 인데, True라고 맞춘 경우(잘한 경우)
False Positive(FP) False 인데, True라고 한 경우(틀렸어요.)
True Negative(TN) False 인데, False라고 맞춘 경우(잘한 경우)
False Negative(FN) True 인데 False 라고 한 경우(틀렸어요.)

TP, TN은 잘 한 경우, FP, FN은 잘못한 경우입니다. 그런데 FP, FN 중에 뭐가 낫냐고 하면, 그건 Case By Case 입니다. 예를 들어 암인데, 암이 아니라고 진단하거나, 암이 아닌데 암이 라고 진단하는 케이스는 어떤 경우가 더 나쁠까요?

그럼 이제 Accuracy, Recall, Precision 에 대해서 알아보도록 하겠습니다. 먼저 Accuracy 는 굉장히 간단합니다. 명확하게 정확도입니다. 정확도라고 생각하면, 즉 전체 중에서 정답을 얼마나 맞춰는가죠.  위의 표를 보시면 total population 이라고 되어 있는데, 그냥 위의 TP+FP+TN+FN, 즉 다 더한겁니다. 즉 전체 합 분의 잘 찾은 경우 즉 TP+TN이 되는 것이죠. 그래서 Accurancy 는 TP+TN/TP+TN+FP+FN 이 됩니다. 간단하죠? 간단하게 말하면, 전체 케이스 중에 정확하게 맞춘 비율입니다.

먼저 precision 은 검출한 것의 정확도라고 할 수 있습니다. 그냥 정확도라고 하면 위의 Accuracy 와 혼동이 오게 되는데, 위의 공식을 보면 TP/Prediction Positive 라고 되어있습니다. Prediction Positive 와 condition positive 가 표에 나오는데 Prediction Positive는 분류를 True 라고 말하는 케이스, Condition Positive 는 실제로 True 인 케이스입니다. 즉 Prediction Positive 는 위의 표에서 TP + FP 가 되구요, Condition Positive 는 TP+FN 이 됩니다. 위의 그림대로입니다. 다시 precision으로 돌아와서 간단하게 TP/TP+FP 입니다. 즉 True라고 분류했으면, 진짜 True 일 확률입니다.

그럼 이제 Recall 은 무엇인가? 검출율이라고 설명하면 쉬운데, 위의 공식을 보면 TP/condition positive 입니다. 즉 TP/TP+FN, 즉 진짜 True 중에 내가 얼마나 TRUE를 제대로 맞췄는가 라고 말할 것인가에 대한 값입니다.

이제 아래의 그림대로 한번 계산을 해보도록 하면…

table2

Accuracy TP+TN/TP+TN+FP+FN 30420/33376 = 0.911
Precision TP/TP+FP 26455/27812 = 0.951
Recall TP/TP+FN 26455/28054 = 0.943

이제 어디가서 좀 아는척 좀 하면 되겠습니다.

[책 리뷰] 파이썬 머신 러닝

해당 리뷰는 지앤선에서 도서를 제공해주셔서 진행하였습니다.

머신러닝이라는 것은 용어가 예전의 클라우드, 빅데이터를 처럼 버즈워드로 시작했다가 어느 순간부터는 대부분의 사람이 알아야 하는 필수가 되어 버렸다. 알파고를 넘어서 “딥러닝”, “강화학습”, 어느 순간 GAN이라는 게 나와서, 스스로 대결해서 스스로 학습해버리는…. 스카이넷이 얼마 남지 않은…

사실 말하기 부끄럽지만, 나름 꽤 많은 머신 러닝 책을 표지만 보고 지나간 사람으로… 내가 공부하기엔 너무 어려운게 아닌가 라는 생각을 여전히 가지고 있습니다. 나름 쉽게 설명하는 머신러닝 강의도 찾아다니고 책도 보는데, 왜 이렇게 어려울까 하는데… 제가 수학이 약했던…

그 중에서 원래 원서가 굉장히 소문이 좋았던 Packt사의 Python Machine Learning 이라는 책이 한국어로 번역이 나와서, 리뷰를 할 수 있는 좋은 기회를 얻었습니다.

 

일단 책의 내용이 굉장히 탄탄합니다. 그러면서 좀 쉽게(여기서의 쉽게는 나름 쉽게고 실제로 아예 여기 관련 내용을 모른다면 꽤 이해하기 어려운… 그래서 제가 잘 이해못하는…) 설명을 하고 있습니다. 실제로 여러 부분을 다루고 있구요. Python 으로 진행하면서, 머신러닝이라는 분야에 대해서 여러가지로 잘 설명하고 있습니다. (전 원래 베이지안이 전부인줄만 알았는데…)

기존의 선형회귀, 로지스틱 회귀, SVM, 에이다 부스팅, K-Means, 딥러닝의 CNN 과 RNN 이야기도 나옵니다.(전 이걸 설명할 능력이 없는…)

사실 이 책의 난이도가, 아무런 배경지식이 없으면 읽기 어렵다고 말씀드릴 수 있습니다. 저도 상당부분은 사실 여전히 이해를 못하고(상당부분 == 거의 다) 그냥 이런게 있구나로만… 머신러닝 책들은 왜 보기만 해도 어느 순간… 눈을 감고 있게 되는지…(기본적으로 수학을 공부하셔야 잘 이해가 될것 같습니다.)

책을 보다보면, 쉬운 부분도 있고, 많이 어려운 부분들도 있는데, 이게 사람마다 체감하는게 완전히 다를 수 있을듯 합니다. 중간에 역전파(백프로파게이션) 을 이해하는데도 한참 걸린… 흑흑흑

그러나 머신러닝은 정말 개발자가 최소한의 지식은 꼭 있어야 할 분야로 보입니다. 다만 이 책은 완전히 초급에서 보기는 그렇고, 최소한 용어가 이해된 중급 수준에서 보면 상당한 도움이 될듯합니다. 한국판 서적중에서 가장 자세한 편입니다.

 

2016년 회고와 2017년 계획

이제 2016년이 정말로 얼마남지 않았다. 이제 곧 2017년…(흑흑흑 나이먹기 싫어요.)
과연 나는 2016년 한해 무엇을 했을까? 먼저 2016년 계획을 찾아보았다.

그런데 검색결과 없다. -_-(그렇다 나의 2016년 계획 따위는 없었던 것이다!!! – 망했어!!!)

그럼 나는 무엇으로 2016년을 회고할 것인가!!!

  1. 인생의 슬픔… 둘째 유산…10월 24일… 뭔가 제대로 확인되지도 못하고 사라진 율율구리 two는 뭔가 슬픔이라는 감정을 느끼기도 전에 무언가 일이 벌어졌던거 같다. 태동을 듣지 못한게, 개인적으로 다행이다 싶기도한… 나보다도 마님이 더 충격적이지 않을까 했는데, 또 그렇게 아무런 기억없이 사라지는… 그냥 뭔가 미안한 마음뿐이다.
  2. RedisConf 2016
    올 한해 일단 가장 큰 기억은 역시 5월 10~11 일에 있었던 redisconf 2016에 참여한 것이다. 미친척 하고 proposal을 던지고, 그게 된지도 모르고 떨어졌다라고 자괴감에 빠져있다가 발표 10일전에 해당 메일을 찾게되서… 부랴부랴 준비했던… 이때 저에게 도움주신 많은 분들에게 감사를… 샌프란에서 몇일 동안 긴장해서 잠도 못자고, 내 발표 끝나고 나서는 한동안 정신을 못차린… 그러나 그 결과는 이제 평생 놀림감으로 남을 유투브 동영상이라니… 그래도 나름 열심히 하긴 했던…
  3. 안식휴가 9월에 한달
    카카오에는 만3년을 다니면 한달을 쉴 수 있는 안식휴가 제도가 있다. 마님과 율율구리와 함께, 한달을 지내는데, 제주도에서 일주일, 부산에서 일주일 정도 지내면서, 뭔가 직장을 다니면서, 안다니는거 같은 느낌을 받았다. 물론 이 시기에도, 버그도 내고, 배포도 하고, 장애도 내는 신기를… 그래도 한달이라는 쉬는 기간은 웬지…

그럼 이제 2017년에는 무엇을 할것인가? 일단 뭔가 2016년에 벌린 일들을 수습하고 새롭게 진행해야 하는데…

  1. 건강
    매년 건강검진때 마다 의사선생님들께 욕 한바가지 먹게 되는게 건강 상태다. 2017년에는 몸무게도 10kg 정도 빼고, 운동을 열심히 해서, 최소한 2016년 올해보다는 좋은 건강상태를 만드는게 1순위
  2. 영어 공부
    매년 얘기하면서도 매년 못하는 영어 공부는 올해는 강제로라도 해보자.
  3. 머신러닝 학습
    올 해는 머신러닝에 대해서도 살짝 공부는 해봐야 겠다.