2017년 1월 29일 일요일

초짜 대학원생의 입장에서 이해하는 Domain-Adversarial Training of Neural Networks (DANN) (3)

Domain-Adversarial Training of Neural Networks -  Yaroslav Ganin 2016 논문을 기본으로 작성한 리뷰.

 

[DANN으로 toy problem 풀어보기]

* Shallow Neural Network & two moon dataset

공부를 할 때 가장 기본은 많이 읽는 것으로 시작해서 그림으로 생각하고, 마지막으로는 코딩을 통해 직접 이론을 implement를 하여 결과를 시각화하는 것이 최고라고 생각합니다. 거기에 더해 요즘은 블로그로 글 정리를 해보고 있는데 이 것도 스스로 공부가 많이 되네요ㅎㅎ

아무튼 앞에서 이론은 열심히 봤으니까 이젠 코딩을 해봅시다. 지난 글 (1), 글 (2)에서 다뤘던 Domain Adaptation (DA) 이론을 hidden layer 수가 한 개씩으로 얕은 Neural Network를 이용하여 간단한 clustering 문제를 풀어보도록 하겠습니다. 본 글에 나오는 예제 코드는 MATLAB으로 작성하였으며 제 github에 올려두었습니다.

* MATLAB보다 Python이 편하신 분은 제 github에 Window 7,10 Python 3.5 tensorflow-gpu 1.0.0.rc2 버전에서 돌아가는 Jupyter notebook으로 올려두었으니 보시면 됩니다. 
다만 본 글은 수식과 연관하여 이해를 돕기 위해 논문의 pseudo code를 그대로 적용한 MATLAB 코드를 기준으로 설명을 진행하겠습니다. 

사실 이 역시도 논문에 포함되어있는 내용이고, 심지어 저자가 toy code를 python으로 작성하여 github에 올려두었지만 제가 MATLAB language로 옮겨 짜면서 새로 data generation 함수를 추가하였고 main 역시도 더 간단하게 딱 실험에 필요한 부분만 남겨 이해를 도울 수 있도록 요약해보았습니다.

먼저 해결하고자 하는 문제를 확인해보겠습니다.



2017년 1월 22일 일요일

초짜 대학원생의 입장에서 이해하는 Domain-Adversarial Training of Neural Networks (DANN) (2)


저번 글에 이어 오늘 포스팅에서는 Domain Adaptation을 뒷받침하는 이론에 대해 살펴보고, 가능하다면 간단한 예제를 직접 코딩하여 풀어보는 것까지 해보겠습니다.




2017년 1월 19일 목요일

초짜 대학원생의 입장에서 이해하는 Domain-Adversarial Training of Neural Networks (DANN) (1)

Domain-Adversarial Training of Neural Networks -  Yaroslav Ganin 2016 논문을 기본으로 작성한 리뷰. 

Domain Adaptation에 GAN을 적용한 이 논문은 사실 GAN의 original paper보다 먼저 봤는데 어쩌다 보니 순서는 거꾸로 설명을 하게 되었습니다 (...아니 사실 내가 본 순서가 이상하지..-_-)
Domain Adaptation도 GAN에 비견할만큼 주목받고 있는데 이 논문은 심지어 이 분야에 GAN을 적용해 합쳐버린 논문입니다!

이 주제는 전이 학습(transfer learning)이라는 또 다른 역사가 깊고 활발히 연구되고 있는 분야와 직접적인 관계가 있기 때문에 여러 모로 알아두면 좋은 논문.....이라고 해서 저자를 보면 역시나 네임드 Hugo Larochelle이 떡하니 박혀있네요 (무슨 만화 원피스 삼대장 느낌이다..).

본격적으로 논문 내용을 다루기 전에 기본적으로 알면 이해에 도움이 될 배경지식을 잠시 소개하고 가겠습니다.




2017년 1월 15일 일요일

초짜 대학원생 입장에서 이해하는 Generative Adversarial Nets (2)

앞서 초짜 대학원생 입장에서 이해하는 Generative Adversarial Nets (1)에 이어서 큰 줄기 두 가지 중 하나였던 이론적 증명 부분을 정리해보겠습니다.




자신의 blogger/blogspot에서 LaTex equations align 맞추기 (mathjax, equation 등호 tab 간격)

수식을 전개하다 보면 등호가 계속 이어질 때가 있다.
$$A = B = C = \cdots = Z .$$
이 때,
$$\begin{align}A & = B \\ & = C \\ &= \cdots \\ &= Z. \end{align} $$
이렇게 쓰고 싶을 때가 있다. 생각보다 쉬운데 다음과 같이 써주기만 하면 된다.
$$\begin{align}A & = B \\ & = C \\ &= \cdots \\ &= Z. \end{align} $$



자신의 blogger/blogspot에서 LaTex theorem-like environment 작성 가능하게 만들기 (mathjax)

수식 작성을 하다보면 간혹 theorem이라든가 lemma, proposition, definition 등은 논문에서 나오는 형식으로 이쁘게 구별이 되었으면 할 때가 있다. 그리고 앞에서 나온 Theorem에 숫자가 자동으로 붙으면 금상첨화!

The global minimum of the virtual training criterion $C(G)$ is achieved if and only if $p_g=g+{data}.$ At that point, $C(G)$ achieves the value $-log(4)$.
$\mathbb{E}_{x \sim p_{data}} \left[ -log(2)\right] + \mathbb{E}_{x \sim p_{g}} \left[ -log(2)\right]$

뭐 이런 식으로?

그럼 어떻게 해야 하는 지 확인해 보자;
  1. blogger에 로그인 하고
  2. 템플릿 설정에 들어간 후
  3. 맞춤 설정을 클릭하고 
  4. 사이드 바에서 고급을 클릭
  5. CSS 추가로 들어가서 아래 내용을 추가해주면 끝난다. 

body
{
counter-reset: theorem;
counter-reset: definition;
}

.theorem {
    display: block;
    margin: 12px 0;
    font-style: italic;
    counter-increment: theorem
}
.theorem:before {
    content: "Theorem " counter(theorem) ".";
    font-weight: bold;
    font-style: normal;
}
.proposition {
    display: block;
    margin: 12px 0;
    font-style: normal;
    counter-increment: proposition
}
.proposition:before {
    content: "Proposition " counter(proposition) ".";
    font-weight: bold;
    font-style: normal;
}
.lemma {
    display: block;
    margin: 12px 0;
    font-style: italic;
    counter-increment: theorem;
}
.lemma:before {
    content: "Lemma " counter(theorem) ".";
    font-weight: bold;
    font-style: normal;
}
.proof {
    display: block;
    margin: 12px 0;
    font-style: normal;
}
.proof:before {
    content: "Proof.";
    font-style: italic;
}
.proof:after {
    content: "\25FC";
    float:right;
}
.definition {
    display: block;
    margin: 12px 0;
    font-style: normal;
    counter-increment: definition
}
.definition:before {
    content: "Definition " counter(definition) ".";
    font-weight: bold;
    font-style: normal;
}



초짜 대학원생 입장에서 이해하는 Generative Adversarial Nets (1)

* Generative Adversarial Nets - Ian Goodfellow et al. 2014 논문을 기본으로 작성한 리뷰. 

NIPS 2016에서 가장 hot한 키워드를 하나 꼽으라 한다면 Generative Adversarial Network(GAN)이라고 단언할 수 있을 정도로 2014년에 Ian Goodfellow(이름 한 번 독특하네..웬만해서는 이름 쉽게 못 외우는데 한 번에 외웠네요 좋은 친구라니 ㅋㅋ)가 NIPS에서 발표한 paper에서 시작한 GAN 붐은 2016년에 더 크게 터진 것 같습니다.

과연 facebook의 Yann Lecun 교수님이 근 10-20년 간에 기계학습 나온 아이디어 중 최고라고 할만하구나(근데 너무 자주, 여러 번, 모든 곳에서 얘기하시는 듯...뭐..그만큼 중요하단 얘긴가...)란 느낌이 들 정도로 이미지 생성(image generation) 외에도 natural language processing(NLP) 등 다양한 분야에서 엄청난 성과들을 보여주고 있습니다.

당장 TensorFlow나 MatConvNet으로 GAN을 구현해서 뭔가 좀 더 새로운 것을 해내야...졸업을 시작?할 수라도 있을 것 같은 불쌍한 대전의 대학원생은 일단 GAN에 대해 또 열심히 공부를 하기 시작했고...orz... 그 일환으로 Ian Goodfellow의 NIPS 2014 paper를 나름대로 정리해 보았습니다.




2017년 1월 13일 금요일

Backpropagation 설명 예제와 함께 완전히 이해하기

기계학습에 대해 관심을 갖고 신경망(Neural Networks, NN)을 처음 접하면서 가장 신비롭게 여겨졌던 부분이 바로 역전파(Backpropagation)를 통한 네트워크 학습(learning or training)이었습니다.
"신경망은 구체적으로 어떻게 학습이 되는거지?"
뭔가 직관적인 설명으로는 신경망이 계산한 답과 정답 사이의 오차를 계산하고 그 오차를 줄이도록 피드백을 주어 학습을 시킨다고 하는데....
1. 구체적으로 어떻게 그 변화 값들을 구하고 전파하는거지?
2. 그리고 그 방법이 "왜" 되는 것이지? 
그리고 역전파에 대해 어느 정도 머리로 이해하고 나서는...

생각보다 단순하고 매우 쉬운 수학만을 사용하네..
어짜피 Backpropagation은 이미 여러 라이브러리에서 잘 구현이 되어있어 사실상 내가 전혀 신경 쓸 일도 없을텐데 머리로 이해했으면 되었지 굳이 직접 손으로 풀어보고 코드를 짜보는 등 시간을 더 투자해야 할까? 등의 생각이 들었습니다.

먼저 마지막 의문에 대해서는 cs231n 수업 명강사로 유명한 Andrej Karpathy가 최근 쓴 글이 아주 잘 답변을 해주고 있죠; Yes you should understand backprop.
네 잘 알아야하고 코딩도 스스로 해봐야한다네요ㅎㅎ
저 글을 한 문장으로 요약하자면 다음과 같습니다:
"The problem with Backpropagation is that it is a leaky abstraction."
즉, 자칫하면 뉴럴 네트워크의 학습 과정을 추상적으로만 생각하고 지나가버리는 함정에 빠질 수 있다는 것!
실제로 구현해보지 않고 머리로만 이해한 사람은 신경망을 설계할 때, 단순히 layer를 쌓아주기만 하면 역전파(Backprop)가 "magically make them work on your data"라고 믿게 될 수 있으나...

실제로는 절대로 생각처럼 이상적으로 돌아가지만은 않고 여러가지 문제점들이 생길 수 있으며, 대표적으로 sigmoid나 tanh 함수가 saturate 되어 생기는 vanishing gradient 문제, dying ReLUs 문제 등을 자세히 소개해주고 있습니다. 관심있는 분들은 원글을 한 번 읽어보시길.

그럼 이 부분은 Andrej Karpathy에게 넘기고, 여기서는 첫 번째 의문에 대해 나름대로 정리해보겠습니다. 

물론 이미 같은 내용에 대한 답을 하기 위해 많은 자료들이 인터넷에 존재하고 여러 사람들이 다양한 관점으로 설명을 잘 해두었지만, 역시 무엇이든 제대로 이해하기 위해서는 스스로 시간을 투자해서 공부한 것을 나만의 언어와 논리로 정리하고 소화할 필요가 있는 것 같습니다.
이해를 위해 하는 것인데 너무 복잡한 문제로 시작하면 문제 자체보다 푸는 기술에만 집중할 수 있으니 가장 단순한 binary classification 문제에서 시작해보겠습니다. 

Classification problems with two classes (binary classification)

Binary (0 or 1) classification 문제를 풀 때, 기존의 신경망 구조는 마지막 output layer의 unit이 하나만 있어서 하나의 scalar 값을 계산하여 결과로 내보냅니다. 이 때, logistic function을 cross entropy loss function과 결합하여 사용하면 scalar 값이 0과 1 사이로 한정되면서 sum-of-squared loss와는 달리 두 가지 클래스 중 하나의 클래스에 대한 확률 값으로 자연스러운 해석이 가능해지죠.

Multiple, independent, binary classification 문제로의 확장은 아주 쉬운데, 각각의 target이 independent하므로 loglikelihood들을 더해주면 됩니다. 즉, 단일 unit이었던 때(single target)와 달리 마지막 layer에서 여러 unit을 갖습니다; 그림1
예시를 들자면 아마 이진 값으로 채워져있는 흑백 이미지 벡터를 생각하면 되지 않을까 싶네요. 그러면 각각의 픽셀에 대해 값이 있는지 없는지를 확률적으로 계산하는 문제가 되겠습니다. 

여기서 multi-class 문제로 좀 더 확장하는 것은 생각보다 간단하고 심지어 수식을 유도해보면 binary 문제와 거의 다를 것이 없습니다. 하지만 정작 이 글의 주제인 역전파에서 벗어날 수 있기 때문에 이 얘기는 다음에 따로 정리해보겠습니다. 

Backpropagation in 2-layer neural network

이제 이 문제를 가장 간단한 구조의 2-layer neural network로 풀기 위해 backpropagation을 계산해보며 실제로 네트워크가 어떻게 "학습"하는 지 확인해보겠습니다.

그림 1. 2-layer neural network

* Layer의 개수가 3개인데 왜 2-layer NN이라 하냐면 보통 neural network의 input layer는 세지 않기 때문에 그렇습니다.
** fully connected이기 때문에 각 층 사이에는 weight 값을 갖는 연결이 모든 조합에 대해 존재하고 편의상 그림에서는 생략해두었습니다. 
*** Hidden layer와 output layer의 activation function은 sigmoid 함수로 통일합니다. 


앞서 문제를 설정한대로 우리의 error function, E는 다음과 같습니다. 
$$E = -\sum_{i=1}^{nout}(t_i log(x_i)+(1-t_i)log(1-x_i))$$
where, $x_i = \frac{1}{1+e^{-s_i}}$, $s_i = \sum_{j=1}x_jw_{ji}$.

수식이 무엇을 의미하는지 직관적으로 이해하려면 극단적인 예제를 넣어보는게 가장 빠르죠ㅎㅎ 실제 class가 1일 때($t_i=1$), 신경망이 계산한 답이 1일 확률이 0이라는($x_i = 0$) output 결과가 나왔다고 해보고 E 값을 계산해보면 쉽게 무한대가 나오는 것을 알 수 있습니다.
반대로 제대로 확률 값이 1 즉, target $t_i$의 class가 1일 때, 실제로 1이라고 계산할 확률이 100%라고($x_i=1$) 신경망이 결과를 내었다면, E 값은 0으로 최소값을 갖습니다. 
즉, 우리의 목표는 E 값을 줄이는 것.
그럼 이제 이 오차 값을 줄이는 방향으로 네트워크를 업데이트 하면 되는데...
여기서 gradient descent라는 개념이 나옵니다. 
어떤 함수 $f$의 임의의 점 $x$에서의 구배(gradient)를 계산하면 $x$로부터 단위($\Delta x$)만큼 움직였을 때, $f$ 값이 변화하는 양을 표현하는 벡터가 나오고, 이 벡터는 항상 가장 가파르게 $f$ 값이 증가하는 방향을 가르키기 때문에 함수 $f$를 E로 두고 구배가 가르키는 반대방향(descent)으로 네트워크를 업데이트 해주면 됩니다. 

Data인 input을 바꾸는 것이 목적이 아니기 때문에 네트워크의 output 값에 영향을 주는 변수 중 우리가 수정할 것은 layer 간의 weight, $w$들입니다. 따라서 우리가 해야하는 것은 각 layer의 weight에 대한 E 함수의 gradient를 계산하고 이 변화량을 원래 w에 반대 방향 (negartive, -1)으로 더해주는 것이죠. 


신경망이 학습하는 것을 순서대로 나열해보면, Input layer로부터 각 layer를 지나치며 weight들을 곱하고, activation function을 지난 다음, 마지막 output layer에서 오차 값을 계산한 이후(feed forward), 업데이트를 위해 순차적으로 거꾸로(back) 돌아가야(propagation)합니다.
따라서 돌아갈 때 순서대로 가장 바깥 쪽 output과 hidden layer 사이의 weight부터 바꿔보겠습니다. $i$번째 output인 $x_i$에 대한 오차값에 대해 $w_{ji}$가 바뀌어야하는 정도를 계산해려면 다음과 같은 수식이 필요합니다:
$$\frac{\partial E}{\partial w_{ji}} = \frac{\partial E}{\partial x_i} \frac{\partial x_i}{\partial s_i} \frac{\partial s_i}{\partial w_{ji}}$$
  1. $\frac{\partial E}{\partial x_i} = \frac{-t_i}{x_i}+\frac{1-t_i}{1-x_i} = \frac{x_i-t_i}{x_i(1-x_i)}$
  2. $\frac{\partial x_i}{\partial s_i} = x_i(1-x_i)$
  3. $\frac{\partial s_i}{\partial w_{ji}} = x_j$
$$\therefore \frac{\partial E}{\partial w_{ji}} = (x_i-t_i)x_j$$
(여기서 순서를 잠시 짚고 넘어갈 필요가 있습니다. 1번과 2번을 곱하면 $\frac{\partial E}{\partial s_i}$가 나옵니다. 그 후 3번을 차례로 계산하여 곱하면 결과적으로 $\frac{\partial E}{\partial w_{ji}} = (x_i-t_i)x_j$가 됩니다. 먼저 $\frac{\partial E}{\partial s_i}$를 계산했다는 것을 기억해주시면 됩니다.)


같은 논리로 그 다음 hidden과 input layer 간의 weight, $w_{kj}$에 대해 변화량을 계산하면,
$$\frac{\partial E}{\partial w_{kj}} = \frac{\partial E}{\partial s_j} \frac{\partial s_j}{\partial w_{kj}}$$
  1. $\frac{\partial E}{\partial s_j} = \sum_{i=1}^{nout} \frac{\partial E}{\partial s_i}\frac{\partial s_i}{\partial x_j}\frac{\partial x_j}{\partial s_j} = \sum_{i=1}^{nout}(x_i-t_i)(w_{ji})(x_j(1-x_j))$ 
  2. $\frac{\partial s_j}{\partial w_{kj}} = x_k ~(\because s_j=\sum_{k=1}x_kw_{kj})$
$$\therefore \frac{\partial E}{\partial w_{kj}} = \sum_{i=1}^{nout}(x_i-t_i)(w_{ji})(x_j(1-x_j))(x_k)$$
여기서 $x_k$는 feed forward할 때도 $i=\{1,\cdots, nout\}$까지의 모든 값에 영향을 주기 때문에 backprop 때도 $\sum_{i=1}^{nout}$을 고려하여 계산해야합니다. 위 그림에서 빨간 화살표들을 보면 되겠습니다.

여기서도 $\frac{\partial E}{\partial s_j}$를 구한 것을 보실 수 있습니다. 앞에서도 강조했었는데 이걸 기억하면 위에서 유도한 식들을 general multiplayer network로 확장하는 것도 매우 쉽습니다. 각 layer의 $\frac{\partial E}{\partial w_{ij}}$를 구하고 싶다면, 항상 $\frac{\partial E}{\partial s_j}$를 계산하고, $\frac{\partial s_j}{\partial w_{kj}} = x_k$를 곱해주는 식이 되면 됩니다. 

참고문헌: https://www.ics.uci.edu/~pjsadows/notes.pdf
(이 문헌을 참고해서 공부하긴 했지만 보시다보면 수식 전개에서 약간의 오타가 있으니 감안하고 보셔야 합니다.)



2017년 1월 6일 금요일

자신의 blogger/blogspot에서 Highlight code를 아주 간단하게 하는 법

간혹 코드를 올리고 싶은데 그냥 글을 쓰면 예쁘지가 않다. 문법이 잘 눈에 들어오지도 않고 본문과 구별이 되지도 않기 때문에 조금 더 신경 써서 코드를 '잘' 보이게 해줄 필요가 있다. 예를 들어:

#include <iostream>

using namespace std;

int main()
{
    cout << "Hello world!" << endl;
    return 0;
}

와 같은 C++ 코드를 그냥 blogger/blogspot 글쓰기에 작성하면 본문과 전혀 구분이 되지 않는다. 하지만 조금만 신경을 쓰면 아래와 같이 바탕색과 함께 해당 프로그래밍 언어에 맞게 문법을 읽어 적당히 강조를 해주도록 할 수 있다.

#include <iostream>

using namespace std;

int main()
{
    cout << "Hello world!" << endl;
    return 0;
}

다음 링크: https://tohtml.com/cpp/ 를 따라가면 아래와 같은 창이 나오는데,



그림에 표시된 것과 같이 1번 소스코드 창에 자신이 원하는 소스코드를 붙여넣고 style (배경색)과 type(프로그래밍 언어)를 고른 다음 highlight 버튼을 누르면 2번 창에 html 코드와 함께 미리보기가 보인다.
이 html 코드를 복사해서 글 쓰는 곳에 붙여 넣으면 미리보기와 같이 아주 편하게 코드를 강조해줄 수 있다.



2017년 1월 5일 목요일

자신의 blogger/blogspot에서 수식을 LaTex으로 작성하기 + escaping LaTex special characters (mathjax)

앞선 글에서 얘기했지만 블로그 기반을 정할 때 구글 블로거를 고른 큰 이유 중 하나가 바로 "수식을 작성하기 쉬워야한다"는 점이었다. 내가 공부하는 분야가 수학 수식을 작성할 일이 많은데, 많이 쓰는 블로그 글을 쓸 때도 LaTex으로 수식을 작성할 수 있으면 연습도 되고 작성도 훨씬 편하고 이래저래 좋을 것 같아 기준이 되었다.

그런 면에서 구글 블로거에서는 아래 소스만 제대로 넣어주면 블로그에 일반적인 글쓰기 모드에서 작성하면서 바로 LaTex으로 사용할 수 있기에 아주 편하다.

<script type="text/javascript"src="http://cdn.mathjax.org/mathjax/latest/MathJax.js">
MathJax.Hub.Config({extensions: ["tex2jax.js","TeX/AMSmath.js","TeX/AMSsymbols.js"],
jax: ["input/TeX", "output/HTML-CSS"],
tex2jax: {
inlineMath: [ ['\$','\$'], ["\\(","\\)"] ],
displayMath: [ ['\$\$','\$\$'], ["\\[","\\]"] ],
processEscapes: true
},
"HTML-CSS": { availableFonts: ["TeX"] }
});
</script>
  1. 이 소스코드를 복사해서 
  2. Blogger에 로그인하고
  3. 사이드 바의 템플릿 창에 들어가서 HTML 편집을 누른다.
  4. <head> 부분에 붙여넣기하고 변경사항을 저장하면 끝난다. 
* tex2jax: { ~ 부분에 processEscapes: true} 부분이 들어가지 않으면, \$ 등 특정 문자를 LaTex에서 escape하지 못한다. 보통 dollar sign과 같은 LaTex에서 의미를 지니는 문자를 표기하기 위해서 backslash \를 붙이는데, 내가 해둔 것과 같이 processEscapes: true를 써두지 않으면 이 문법이 먹히지 않고 그저 \\\$ 로만 보이게 된다. (mathjax 관련 내용 링크)



페이스북 좋아요 버튼을 포스트에 추가하기 (Facebook Like Button to Blogger Posts)

블로그에 글이 많아지고 블로그 자체가 커지다보면 후에 어떤 글에 댓글이나 반응이 있었는 지 관리하기가 만만찮을 것이다. (겨우 게시물이 세 개 뿐인 지금은 설레발이겠으나..ㅋㅋ)
꼭 이런 목적 외에도 내가 쓴 글이 좋아요와 같은 피드백을 받을 수 있고 이를 자주 들어가는 페이스북을 통해 즉각적으로 알 수 있다면 여러모로 좋지 않을까?

아무튼 그 있을 지 모르는 먼 훗날을 위해! 방법을 찾아보았다. 생각보다 매우 간단한데 다만 영어로 되어있을 뿐ㅋㅋ(원본 링크)
원래는 이렇게 간단하지는 않고 페이스북 개발자 등록을 한 후 html 소스를 받아서 긁어와야하지만 친절하게도 그 소스들을 종류별로 정리해서 두었기에 이 글 대로 따라하는 사람들은 등록을 할 필요가 없다.

한국 사람들을 위해 같은 내용이지만 이를 한글로 번역하고 조금 정리해서 올려본다.
  1. Blogger 에 로긴을 하고
  2. 사이드바의 템플릿 창에 들어가서 HTML 편집을 누른다. 
  3. ctrl+f 로 (맥에서는 cmd + f)로 두 번째 <data:post.body/> 를 찾는다. (즉, find창에 문구를 치고 두 번 엔터를 해야 한다.)
  4. 아래 코드를 복사해서 포스팅의 맨 위에 좋아요 버튼이 나오길 바란다면 저 코드 바로 위에 내용이 끝나고 제일 밑에 나오길 바란다면 저 코드 바로 뒤에 붙여넣기 하면 끝난다. 

Vertical style을 원한다면:
<br/><br/><iframe allowTransparency='true' expr:src='&quot;http://www.facebook.com/plugins/like.php?href=&quot; + data:post.canonicalUrl + &quot;&amp;layout=button_count&amp;show_faces=false&amp;width=100&amp;action=like&amp;font=arial&amp;colorscheme=light&quot;' frameborder='0' scrolling='no' style='border:none; overflow:hidden; width:100px; height:21px;'/>


Horizontal style을 원한다면:
<br/><br/><iframe allowTransparency='true' expr:src='&quot;http://www.facebook.com/plugins/like.php?href=&quot; + data:post.canonicalUrl + &quot;&amp;layout=box_count&amp;show_faces=false&amp;width=100&amp;action=like&amp;font=arial&amp;colorscheme=light&quot;' frameborder='0' scrolling='no' style='border:none; overflow:hidden; width:55px; height:62px;'/>

Standard style을 원한다면:
<br/><br/><iframe allowTransparency='true' expr:src='&quot;http://www.facebook.com/plugins/like.php?href=&quot; + data:post.canonicalUrl + &quot;&amp;layout=standard&amp;show_faces=false&amp;width=100&amp;action=like&amp;font=arial&amp;colorscheme=light&quot;' frameborder='0' scrolling='no' style='border:none; overflow:hidden; width:450px; height:35px;'/>



cs231n Convolutional Neural Network for Visual Recognition - 시작하기 (환경설정)

Machine learning 공부를 기초부터 하기 좋은 자료로 stanford의 cs231n 강의가 있습니다. 아주 최근 강좌(2016 winter)까지도 youtube에 공개되어있고 상당히 친절한 강의라서 시작하는 사람들에게 추천해주기 딱 좋습니다.

사이트에 course lecture note들도 아주 충실하고 실제로 assignment들을 다운받아 기본적인 개념에 대한 코딩을 직접해볼 수도 있는데다 워낙 유명한 강의라 이미 다른 사람들이 시도한 solution들도 쉽게 찾아볼 수 있어서 혼자 공부하기에 최적의 강의라고 생각합니다.

그래서 기초를 다질 겸, 나도 한 번 처음부터 material들을 읽고 숙제들을 하나씩 해봐야겠다는 생각을 하고 시작해봤는데...이게 은근히 '시작' 자체를 하기 위해서 필요한 환경설정이 필요해서 조금 고생했습니다 (레딧에서도 내가 겪은 류의 어려움에 대해 질문하는 글들이 있는 걸 보면 나만 그런 것도 아니다...).

딱히 거창한 것은 아니지만 의욕을 가지고 공부를 하려했는데 이래저래 환경설정으로 막히면 힘이 빠질 수 밖에 없죠 (뭐든지 환경설정이 제일 짜증난다.).
그렇다고 또 어떻게 하면 좋을 지 일괄적으로 정리해 둔 자료는 아무리 찾아봐도 없기에 아예 '무조건 따라하기' 방식으로 내가 환경 설정한 것들을 정리해보았습니다 (윈도우 OS 기준).

1. 먼저 사이트의 글을 읽습니다! 
1번 숙제를 하기 위해 http://cs231n.github.io/assignments2016/assignment1/에 들어가면 setup을 하는 법이 꽤 친절히 나와있는 편입니다. 터미널을 사용하는 법에 대해 먼저 소개가 되어있는데 우리는 스탠포드 학생이 아니고 숙제를 다운받아 개별적으로 해볼 것이기 때문에 'Working locally' 항목을 보면 되겠습니다.

먼저 시키는대로 먼저 code zip 파일을 다운 받고, 옵션이 2가지가 주어지는데, 그 중 저는 아나콘다를 사용했습니다. 사이트에서도 이 방법을 추천하는데 아나콘다를 깔고 사용하면 각종 환경설정을 하는 것이 훨씬 간단하고 수월해지기 때문입니다(...라고 설명합니다 ***).

* 사실 파이썬을 모르면 아나콘다도 뭔가 싶은데 이건 그냥 파이썬을 사용하기 위해 편하게 해주는 일종의 도구라고 생각하면 됩니다. 아나콘다에 대한 설명과 까는 방법은 이 글의 목적을 벗어나기 때문에 다음 링크로 갈음하겠습니다. (http://bigdatapy.tistory.com/105)
** 아나콘다에 파이썬 버전을 선택할 수 있는데 저는 3.5버전을 선택했습니다.
*** "Once you install it you can skip all mentions of requirements and you’re ready to go directly to working on the assignment."라고 적혀있지만 정말 그랬으면 내가 이 고생을 했을리가 없지... 

2. Jupyter notebook 설치
다운받은 code zip을 원하는 곳에 풀고 주소를 기억해둡니다.
cmd창을 킨 다음, conda install jupyter 해서 jupyter notebook이란 것을 사용할 수 있도록 설치를 하겠습니다.


저는 이미 깔려있기 때문에 이미 설치가 되어있다는 메시지가 뜹니다. Jupyter notebook은 내 노트북에서 웹페이지를 기반으로 local하게(인터넷이 되지 않아도) python code를 수정하고 실행해볼 수 있게 해줍니다. 기본적으로 모든 assignment 문서가 notebook으로 작성, 실행해보고 제출하게 되어있기 때문에 필수적인 도구입니다.

3. python 2.7버전 가상환경 만들어주기 
cs231n 사이트는 python을 잘 모르는 사람들을 위한 tutorial를 제공합니다. 그 tutorial에도 나와있지만 강좌에서 사용하는 모든 코드는 파이썬 2.7버전에서'만' 돌아가게 되어있습니다. 

웃긴게 프로그램이든 언어든 버전이 한 단계 올라가면 앞에 버전들을 잘 포괄해서 가져가는 것이 보통인데 파이썬은 3.~버전이 2.~버전과 사용하는 문법이 매.우. 다르죠. 따라서 아나콘다를 파이썬 3.5 버전으로 깐 우리는 jupyter notebook에서 python2 kernel로 돌아가게 하기 위해 새로이 환경을 설정해줘야합니다. 
---
There are currently two different supported versions of Python, 2.7 and 3.4. Somewhat confusingly, Python 3.0 introduced many backwards-incompatible changes to the language, so code written for 2.7 may not work under 3.4 and vice versa. For this class all code will use Python 2.7.
You can check your Python version at the command line by running python --version.
---

* 처음부터 아나콘다를 버전에 맞게 설치해주면 되지 않느냐? 하는 사람들은 ... 음 그래도 됩니다. 근데 제가 그렇게 해보지 않았고.... 
** 아나콘다를 파이썬 3.5 버전으로 깔았다고 해도 그냥 중복으로 아나콘다 파이썬 2.7버전을 또 깔면 되는 것이 아니냐? 하실 수 있는데 그러면 안 됩니다. 그냥 설치를 하면 충돌이 난다고 하네요(http://conda.pydata.org/docs/py2or3.html#create-a-python-2-7-environment).

바로 위에 소개한 링크의 글이 알려주는대로만 하면 가상환경 설정이 끝나고 아마도 아무 문제 없이 jupyter notebook에서 코드들이 실행될 것입니다만.... 그래도 무조건 따라하기 형식이니 한 스텝씩 여기에 정리해보겠습니다.

실행창에 
conda create -n py27 python=2.7 anaconda
라고 치면 가상환경의 이름을 py27이라고 만들어줄 것이고 (맘대로 바꿀 수 있다) 설치 후 내가 가지고 있는 가상환경을 다 확인해보고 싶다면
conda info --envs
라고 치면 목록이 쭉 나옵니다. (그 중에 새로 만든 py27이 포함되있는 것을 확인할 수 있습니다.)

이제 만들 가상환경으로 들어가고 싶으면, 
activate py27
이라고 치면 실행창에서 (py27) C:\Users\Jaejun Yoo> 와 같이 앞에 (py27)이 붙는 것을 볼 수 있습니다. 
이제 우리는 python 2.7 버전을 사용하는 가상환경에 들어와 있는 것입니다. 아마도 아나콘다를 2.7버전으로 깔았고 python 3.5 버전이 필요할 경우에도 비슷한 방식으로 할 수 있을 것으로 보입니다. 

4. Jupyter notebook 켜기
단순한 것인데 처음인 사람들은 당황할 수 있는 것이 jupyter notebook을 키는 것입니다. 그냥 명령창을 켜서
jupyter notebook
이라고 치면 내가 원하는 곳이 아닌 'C:\Users\Jaejun Yoo'과 같은 Default 폴더에서 notebook이 실행되는 것을 볼 수 있습니다. 따라서 아까 기억해뒀던 code zip을 풀은 directory 주소로 들어가서(cd ~), jupyter notebook을 켜면 이제 내가 풀고 싶은 assignment1 'knn.ipynb'를 열어서 시작할 수 있는 것을 볼 수 있습니다. 
여기서 말하는 jupyter notebook은 강의에서 제공하는 tutorial 글 중 IPython notebook 사용법과 동일하니 참고하시면 됩니다. 

5. 데이터 받기
마지막으로 데이터를 받아야하는데..!
Download data: Once you have the starter code, you will need to download the CIFAR-10 dataset. Run the following from the assignment1 directory:
cd cs231n/datasets
./get_datasets.sh
윈도우 OS기반이기 때문에 bash shell을 다음과 같이 명령창에서 직접 수행 할 수가 없습니다. (다른 우회적 방법은 있겠지만) 하지만 .sh 파일이 해주는 것이 그냥 링크로 접근하여 다운로드를 시키는 것이므로 해당 get_datasets.sh 파일을 txt 파일로 읽어 링크만 따오면 됩니다. 아마 다음과 같이 보일텐데... 
즉, http://www.cs.toronto.edu/~kriz/cifar-10-python.tar.gz 이 링크를 들어가면 알아서 다운로드가 진행됩니다. cs231n/datasets 폴더 안에 .tar 파일을 받아서 zip 파일 풀 듯이 풀어주면 됩니다. 

6. 기타
혹시나 이러고서도 'knn.ipynb'에서 error가 난다면 보통 패키지가 import가 안 되어 있는 경우일 것으로 보입니다. 흔히 다음과 같이 에러 메시지가 뜨는데
---------------------------------------------------------------------------
ImportError Traceback (most recent call last)
<ipython-input-3-6d53d297f0cc> in <module>()
3 import random
4 import numpy as np
----> 5 from cs231n.data_utils import load_CIFAR10
6 import matplotlib.pyplot as plt
7
D:\DaumCloud\[3] Study\[0] cs231n CNN for visual recognition - stanford\assignment1\cs231n\data_utils.py in <module>()
2 import numpy as np
3 import os
----> 4 from scipy.misc import imread
5
6 def load_CIFAR_batch(filename):
ImportError: No module named scipy.misc

이 때는 그냥 conda install (없다는 package 이름) 해주면 되겠습니다. 

그러면 모두들 즐거운 공부하시길~

* 만약 이래도 안 되는 것이 있다면 댓글을 남겨주세요 제가 아는 범위라면 최대한 도와드리려고 노력해보겠습니다.



구글 블로그 (Blogger, blogspot) 시작하기

공부를 하다보니 정리를 하면 더 잘 기억에 남고 이해를 할 수 있다는 것을 깨달았다.
그래서 선택한 것이 블로그를 해보는 것이었는데, 처음에는 야심차게 githup에 Jekyll을 이용해서 블로그를 해보려 했으나 하루를 통째로 날리며 생각보다 쉽지는 않다는 결론에 이르렀다. 

여러 블로그 서비스들 중 어떤 것을 고를 지를 고민하면서 블로깅의 목적을 다시 한 번 생각해보았다. 일단 공부를 하고 정보를 아카이브하기 위한 목적이었기 때문에 다음과 같이 상당히 단순한? 네 가지 기능을 충족하기만 되었는데... 단순하다 생각했지만 생각보다 다 만족하는 블로그 서비스를 찾기는 어려웠다. 

  1. 블로그 내 검색이 되어야 한다. 
  2. 수식(LaTex) 작성이 용이해야 한다. 
  3. 글 작성 및 Image 업로드가 번거롭지 않고 쉬워야한다. 
  4. 서비스가 계속 유지되어야 한다. (구글느님은 영원할 것이야!)
그래서 나름 열심히 찾아본 결과 구글 블로거 (blogger)가 상당히 내 취지에 부합한다는 결론을 내렸다. 물론 블로거를 처음 시작하면서도 블로그를 처음 해보는 입장에서는 약간씩 어려운 점들이 있었지..만 github보다는 백만배 나았던 듯.. (언젠가는 github으로 블로그 하는 것에 성공하고 말겠다...orz..).
아무튼 오늘 블로그를 처음 시작하면서 느낀 소소한 점들에 대해 정리하는 것으로 블로그를 시작해볼까 한다. 





Hello World!

This is my first note on my blog. As usual..Hello World!