이스트소프트 AI Plus Lab
 * 컴퓨터 비전
 * 자연어 처리
 * 악성코드 탐지
 * 금융시장 예측

[[Tableofcontents]]

== 딥러닝의 원리 ==
=== 딥러닝의 이해 ===
 * 인공지능
  * 사람만큼이나 사람보다 똑똑한 기계
 * 머신러닝 
  * 더 많은 데이터를 더 빠르게 처리할 수 있지만, 처리 알고리즘은 사람이 만들어야 한다
  * 사람보다 똑똑한 기계를 만들기 위해 사람(생물)이 학습하는 방법을 모델링
   * 데이터로부터 경험적, 귀납적으로 만들어낸 알고리즘에 의해 추론
   * feature와 label
   * 더 좋은 feature들을 추출할 수 있다면, 더욱 쉽게 분류할 수 있다
   * feature engineering 
    * 딥러닝 이전 머신러닝에서 반드시 수행되어야하는 작업
    * 사람이 정답을 더 잘 찾기 위한 특징을 찾아내고 (->도메인 전문가) 
    * 사람이 데이터에서 그런 특징을 식별하고 추출하는 알고리즘을 설계하는 것 (->알고리즘)
  * 단일 층으로 분류가 불가능하다면, 분류가 가능할 때까지 공간을 변형시키면 된다
   * 즉, 다중 층을 사용하면 된다
 * 딥러닝
  * 여러 층을 통째로 학습시키면(차원이 늘어나면) 
  * 사람이 찾을 수 있는 특징보다 더 좋은 특징을 찾아 분류를 할 수 있다
  * 이 특징은 사람이 이해하기에는 어려울 수 있다
  * 더 어렵고 복잡한 문제를 해결할 수 있는데 이를 수용력이라 함
  * 딥러닝은 머신러닝 더 넓은 수용력을 가지는 학습 방법
  * 학습할 데이터가 충분히 많아야 더욱 정확하고 복잡한 특징을 추출할 수 있게 된다
 * 딥러닝에 필요한 것들
  * 선형대수학
  * 확률과 통계
  * 다변수 미적분
  * 알고리즘, 최적화
  * 기타 등등
   * 정보이론(엔트로피 ..)
   * 기타 수학적 이론들
 === 딥러닝의 원리 1 - similarity ===
  * 딥러닝에서는 스스로 좋은 feature를 찾아가기 때문에 최대한 손실이 없는 데이터를 사용하는 것이 유리하다
  * 벡터의 유사도를 나타내는 방법
   * 유클리드 거리(두 벡터의 차이)
   * 코사인 유사도(두 벡터의 내적)
   * 하지만 유사한 데이터라고 해서 유사한 벡터인 것은 아니다
   * 이를 해결하는 것이 머신러닝의 핵심적인 목교
  * 입력층 벡터를 유사하게 -> 입력 데이터의 모델링
  * 마지막 은닉 층 벡터를 유사하게 -> 네트워크 모델링
  * Supervised Learning
   * 분류의 정답인 함수 값을 통해 어떤 데이터들이 분류가 같아야 하고, 분류가 달라야하는지
   * 기준을 가르치는 것
  * 뉴럴 네트워크를 학습한다는 것
   * 학습한다는 것은 정답과의 오차를 줄이는 방향으로 모델 파라미터를 수정해 나가는 것
   * 학습이 잘 된 후에는 어떤 입력에 대해 강하게 반응하려면 가중치가 그 벡터와 유사해 진다
  * 모델링
   * 더 적은 데이터를 가지고 더 적합한 학습을 시킬 수 있도록하는 것이 모델링
   * ex) CNN
  * 응용
   * 변종 악성코드의 탐지와 분류
   * 악성코드의 유사도
    * 메타데이터가 유사하다
    * 파일 구조와 내용이 유사
    * 코드 패턴, 행위 패턴이 유사
    * 사용하는 API가 유사
    * 개발자의 습관이 유사
    * 노리는 대상이나 취약점이 유사
    * 통신하는 대상이나 패킷이 유사
    * 압축, 난독화, 암호화, 패키지 방식이 유사
    * 악성 여부?
     * 정말 모든 악성 코드를 유사한가?
     * 정말 모든 정상 코드는 유사한가?
     * 정말 정상코드와 악성코드는 유사하지 않은가?
    * 탐지명
     * 보안 분석가들이 오랜 기간동안 악성코드를 분류
     * 유사한 악성코드를 같은 탐지명으로 분류할까?
     * 같은 탐지명으로 분류된 악성코드들은 유사할까?
     * 하나의 악성코드는 하나의 탐지명으로만 분류할 수 있을까?
    * 탐지명을 label로 학습을 시킨다 하더라도
   * 신종 악성코드의 탐지와 분류
    * 학습한 데이터의 유사한 악성코드가 없다
    * 학습한 훈련 데이터에 같은 분류로 분류된 악성코드가 없다
=== 딥러닝의 원리 2 - Probability ===
 * 변별 모델 
  * classification, regression
  * 입력 데이터 x가 주어질 때, 간단한 응답 y를 결정
  * 조건부 확률을 사용
   * 조건부 확률의 함정
   * 조건부 활률 뒤집기
    * 수 많은 경우의 수가 존재하므로 직접 계산하는 것은 굉장히 어렵다
    * 결합 확률
     * x,y가 동시에 일어날 확률
     * 베이즈 정리에 의해 계산     
    * 결합 확률을 계산
 * 생성모델
  * y라는 속성을 같는 그럴듯한 x를 생성
  * 딥러닝을 활용하면 y뿐만아니라 대량의 x로부터 숨겨진 특징 z를 찾아낼 수 있다
  * 가르친 적 없는 x를 생성
  * 딥러닝 기반 생성모델 VAEs, GANs, Auto-Regressive model, DBNs, RBMs
 

== ~~(딥)~~러닝 ==
[http://cs231n.stanford.edu/]
 이미지 분류기 
 * 이미지 데이터를 각 픽셀에 대해 rgb로 표현 
 * 다른 시각에서, 다른 성질을 가진 같은 물체를 어떻게 같은 label로 분류할 것인가
 * hard-code로는 분류기를 만드는 것이 불가능함
=== K Nearest Neighbor Classifier ===
  * 이미지를 학습하여 저장
  * 새로 들어온 이미지를 차이가 가장 작은 값을 통해 분류
  * 비교하는 방법
   * 픽셀값으 절대값 거리 계산
   * 이를 distance로 사용
  * 분류 시간이 linear하게 증가
  * CNN 모델에서는 학습시간은 증가하지만, 분류가 빠름
  * hyper parameter
   * L1 distance vs L2 distance 
   * K?
   * 실험적으로 hyper parameter를 결정
    * 학습 데이터 중 일부를 validation data로 사용
    * cross-validation
=== Linear Classification ===
 * 선을 그어 분류하는 방법
 * non-parametric approach
  * KNN 등
 * parametric approach 
  * 선의 기울기를 사용하여
  * f(x, W) -> 분류
  * score function f =  W*x + b = 점수의 벡터
 * loss function
  * 학습 데이터에 대해 unhappiness를 측정하는 함수
  * loss function을 작게 만드는 과정 -> optimization
  * ex) SVM loss function
 * softmax classifier
  * score = 특정 분류에 대한 normalized 되지 않은 조건부 확률 
  * loss function = -log(normalized score)
 * optimization
  * loss function을 최소화하는 W을 구하는 과정
  * random search 
   * W를 랜덤하게 생성하여 찾은 W 중 가장 loss 값을 가지는 W를 선택
   * 낮은 정확도
  * gradient descent
   * 가능한 작은 h를 사용하여 gradient를 측정
   * loss가 작아지는 방향으로 점진적으로 접근  

== 고래 등에 태운 텐서플로 ==
https://goo.gl/M1zJVP


 1. sudo docker rm -f tensorflow
 1. sudo docker run -d --net=host --name tensorflow gcr.io/tensorflow/tensorflow
 1. connect http://127.0.0.1:8888/ 
 1. try login
 1. sudo docker logs tensorflow
 1. http://localhost:8888/?token=00bca78fdb2b3ab7b23eab7105dc639dab72d021ecd5c54f <- copy link like this to browser/


```
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function

import argparse
import os
import sys
import time

from six.moves import xrange
import tensorflow as tf

from tensorflow.examples.tutorials.mnist import input_data
from tensorflow.examples.tutorials.mnist import mnist

FLAGS = None


def placeholder_inputs(batch_size):
    images_placeholder = tf.placeholder(tf.float32, shape=(batch_size,
                                                           mnist.IMAGE_PIXELS))
    labels_placeholder = tf.placeholder(tf.int32, shape=(batch_size))
    return images_placeholder, labels_placeholder


def fill_feed_dict(data_set, images_pl, labels_pl):
    images_feed, labels_feed = data_set.next_batch(FLAGS.batch_size,
                                                   FLAGS.fake_data)
    feed_dict = {
        images_pl: images_feed,
        labels_pl: labels_feed,
    }
    return feed_dict


def do_eval(sess,
            eval_correct,
            images_placeholder,
            labels_placeholder,
            data_set):

    true_count = 0
    steps_per_epoch = data_set.num_examples // FLAGS.batch_size
    num_examples = steps_per_epoch * FLAGS.batch_size
    for step in xrange(steps_per_epoch):
        feed_dict = fill_feed_dict(data_set,
                                   images_placeholder,
                                   labels_placeholder)
        true_count += sess.run(eval_correct, feed_dict=feed_dict)
    precision = float(true_count) / num_examples
    print('  Num examples: %d  Num correct: %d  Precision @ 1: %0.04f' %
          (num_examples, true_count, precision))


def run_training():
    data_sets = input_data.read_data_sets(FLAGS.input_data_dir, FLAGS.fake_data)

    with tf.Graph().as_default():
        images_placeholder, labels_placeholder = placeholder_inputs(
            FLAGS.batch_size)

        logits = mnist.inference(images_placeholder,
                                 FLAGS.hidden1,
                                 FLAGS.hidden2)

        loss = mnist.loss(logits, labels_placeholder)

        train_op = mnist.training(loss, FLAGS.learning_rate)

        eval_correct = mnist.evaluation(logits, labels_placeholder)

        summary = tf.summary.merge_all()

        init = tf.global_variables_initializer()

        saver = tf.train.Saver()

        sess = tf.Session()

        summary_writer = tf.summary.FileWriter(FLAGS.log_dir, sess.graph)

        sess.run(init)

        for step in xrange(FLAGS.max_steps):
            start_time = time.time()

            feed_dict = fill_feed_dict(data_sets.train,
                                       images_placeholder,
                                       labels_placeholder)

            _, loss_value = sess.run([train_op, loss],
                                     feed_dict=feed_dict)

            duration = time.time() - start_time

            if step % 100 == 0:
                print('Step %d: loss = %.2f (%.3f sec)' % (step, loss_value, duration))
                summary_str = sess.run(summary, feed_dict=feed_dict)
                summary_writer.add_summary(summary_str, step)
                summary_writer.flush()

            if (step + 1) % 1000 == 0 or (step + 1) == FLAGS.max_steps:
                checkpoint_file = os.path.join(FLAGS.log_dir, 'model.ckpt')
                saver.save(sess, checkpoint_file, global_step=step)
                print('Training Data Eval:')
                do_eval(sess,
                        eval_correct,
                        images_placeholder,
                        labels_placeholder,
                        data_sets.train)
                print('Validation Data Eval:')
                do_eval(sess,
                        eval_correct,
                        images_placeholder,
                        labels_placeholder,
                        data_sets.validation)
                print('Test Data Eval:')
                do_eval(sess,
                        eval_correct,
                        images_placeholder,
                        labels_placeholder,
                        data_sets.test)


def main(_):
    if tf.gfile.Exists(FLAGS.log_dir):
        tf.gfile.DeleteRecursively(FLAGS.log_dir)
    tf.gfile.MakeDirs(FLAGS.log_dir)
    run_training()


if __name__ == '__main__':
    parser = argparse.ArgumentParser()
    parser.add_argument(
        '--learning_rate',
        type=float,
        default=0.01,
        help='Initial learning rate.'
    )
    parser.add_argument(
        '--max_steps',
        type=int,
        default=2000,
        help='Number of steps to run trainer.'
    )
    parser.add_argument(
        '--hidden1',
        type=int,
        default=128,
        help='Number of units in hidden layer 1.'
    )
    parser.add_argument(
        '--hidden2',
        type=int,
        default=32,
        help='Number of units in hidden layer 2.'
    )
    parser.add_argument(
        '--batch_size',
        type=int,
        default=100,
        help='Batch size.  Must divide evenly into the dataset sizes.'
    )
    parser.add_argument(
        '--input_data_dir',
        type=str,
        default=os.path.join(os.getenv('TEST_TMPDIR', '/tmp'),
                             'tensorflow/mnist/input_data'),
        help='Directory to put the input data.'
    )
    parser.add_argument(
        '--log_dir',
        type=str,
        default=os.path.join(os.getenv('TEST_TMPDIR', '/tmp'),
                             'tensorflow/mnist/logs/fully_connected_feed'),
        help='Directory to put the log data.'
    )
    parser.add_argument(
        '--fake_data',
        default=False,
        help='If true, uses fake data for unit testing.',
        action='store_true'
    )

FLAGS, unparsed = parser.parse_known_args()
tf.app.run(main=main, argv=[sys.argv[0]] + unparsed)
```

```
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function

import math

import tensorflow as tf

NUM_CLASSES = 10

IMAGE_SIZE = 28
IMAGE_PIXELS = IMAGE_SIZE * IMAGE_SIZE


def inference(images, hidden1_units, hidden2_units):
    with tf.name_scope('hidden1'):
        weights = tf.Variable(
            tf.truncated_normal([IMAGE_PIXELS, hidden1_units],
                                stddev=1.0 / math.sqrt(float(IMAGE_PIXELS))),
            name='weights')
        biases = tf.Variable(tf.zeros([hidden1_units]),
                             name='biases')
        hidden1 = tf.nn.relu(tf.matmul(images, weights) + biases)

    with tf.name_scope('hidden2'):
        weights = tf.Variable(
            tf.truncated_normal([hidden1_units, hidden2_units],
                                stddev=1.0 / math.sqrt(float(hidden1_units))),
            name='weights')
        biases = tf.Variable(tf.zeros([hidden2_units]),
                         name='biases')
        hidden2 = tf.nn.relu(tf.matmul(hidden1, weights) + biases)

    with tf.name_scope('softmax_linear'):
        weights = tf.Variable(
            tf.truncated_normal([hidden2_units, NUM_CLASSES],
                                stddev=1.0 / math.sqrt(float(hidden2_units))),
            name='weights')
        biases = tf.Variable(tf.zeros([NUM_CLASSES]),
                         name='biases')
        logits = tf.matmul(hidden2, weights) + biases
    return logits


def loss(logits, labels):
    labels = tf.to_int64(labels)
    cross_entropy = tf.nn.sparse_softmax_cross_entropy_with_logits(
        labels=labels, logits=logits, name='xentropy')
    return tf.reduce_mean(cross_entropy, name='xentropy_mean')


def training(loss, learning_rate):
    tf.summary.scalar('loss', loss)
    optimizer = tf.train.GradientDescentOptimizer(learning_rate)
    global_step = tf.Variable(0, name='global_step', trainable=False)
    train_op = optimizer.minimize(loss, global_step=global_step)
    return train_op


def evaluation(logits, labels):
    correct = tf.nn.in_top_k(logits, labels, 1)
    return tf.reduce_sum(tf.cast(correct, tf.int32))
```

== 딥러닝과 자연어 처리 == 
== 인공지능의 미래 ==