디시인사이드 갤러리

갤러리 이슈박스, 최근방문 갤러리

갤러리 본문 영역

잉여잉여 퍼셉트론 - 4

DMW(119.204) 2009.07.05 20:46:31
조회 4266 추천 1 댓글 5




이번엔 잘 올라가려나.........


-----------------------------------------------------------------------------------------------------------------------------
 이번에는 퍼셉트론 학습 방법에 대해서 알아보고 그걸 더러운 C++로 구현해 볼껀데...그전에 신경망의 의한 패턴 분류가 어떻게 일루어 지는지를 살펴보자능. 이제 끝임 하악하악


페턴 분류

 일단 페턴이란거 뭐냐믄.....어떤 오브젝트를 정량적으로 표현한거라구 한다능. 외우고 있긴 하지만 이게 뭔소린진 나도 가슴으로 느껴지진 않네 -_-;;; 아무튼 페턴은 크가 공간 페턴 spatial pattern 이랑 시변 페턴 temporal pattern 으로 구분된다능. 공간 페턴은 쉽게 말하면 그림, 그러니까 이미지이고 시변 페턴은 음성 신호, 심전도 파형같은 것들이라능.

 페턴 분류 시스템은 아래 그림과 같은 걸로 구성되 있다능. 일단 그림을 보고 하나씩 살펴보자능.


 입력은 그냥 입력이구....트랜스튜서 transducer라는건 실 세계의 데이터를 입력받아서 뉴로 컴퓨터, 그러니까 신경망이 처리하기 용이한 형태로 변환하는 기능을 한다능. 디지털데이터를 다루는 신경망이면 디지털로 바꾸고 아날로그 데이터를 다루는 신경망이면 아날로그로 바꾸는거라능. 트랜스튜서의 출력을 페턴 백터 pattern vector 라구 한다능.

  요 페턴 백터를 가지구 바로 분류기 classifier 에 입력해도 상관은 업ㅂ지만 특징 추출기feature extractor 를 한번 거쳐서 분류할 페턴들 간의 특징이 잘 드러나도록 하면 분류기의 성능을 더 높일 수있따능. 이제 특징 추출기에서 뽑아낸 특징 백터를 분류기로 분류하면 되는거라능. 단층 신경망을 사용한 패턴 분류기는 대충이런식이라능


 입력층 뉴런은 n개고 그걸 m개의 클러스터로 분류하는 분류기의 그림이라능. 그래서 출력층 뉴런이 m개임. 아무튼 이 뉴런들의 출력값중에 가장 큰값을 선택해서 입력된 특징 백터 x가 어떤 클러스터에 속하는지를 판별해 내는거라능

신경망의 패턴 분류

 이제 신경망이 페턴을 어떻게 분류해 내는지를 또 보자. 이거까지만 알아보구 퍼셉트론 만들어 볼꺼라능. n차원의 패턴 공간에서 요렇게 생긴 패턴 하나는 하나의 점으로 표시 할 수 있다능.

x = [ x1 x2 x3 ... xn ]

비슷한 페턴들은 패턴 공간에서 끼리끼리 뭉쳐있을꺼라능. 그러니까 대충 이런 그림이 나올꺼라능.


 저 빨간선을 기준으로 페턴을 두 그룹 j랑 k로 으로 나눌 수 있다능. 저 빨간선을 판단면 decision surface 라고 한다능. 그그에서는 패턴 공간이 2차원이라 선으로 표현된거구 페턴이 n차원이라면 n차원 초평면 hyperplane 이 될꺼심. 그리구 이 판단면을 정의하는 함수를 판별 함수 discriminant function 라구 한다능.

 d(x)를 판별 함수라고 치구 dk(x)랑 dj(x) 를  각 그룹에 속한 패턴 x의 판별 함수 값이라고 하자. 그러면 어떤 패턴 x가 다음 조건을 만족하면 k 그룹에 속해 있다고 할 수 있다능.

dk(x) > dj(x)         j ≠ k,  j = 1, 2, 3, ...... R

 R 은 클러스터의 갯수라능. 만약 패턴들을 두개의 클러스터로 분류하는 경우일 때

d1(x) = d2(x)          or         d1(x) - d2(x) = 0

 이 된다면 클러스터 1, 2의 경계면이기 때문에 어떤 클러스터에 속한다고 말할 수 업ㅂ게된다. 바루 위에 있는 식을판변면이라구 한다능. 그러면 T가 0인 양극성 계단 함수를 쓰는 신경망으로 패턴을 두개로 분류한다고 해보자. 입력 패턴이클러스터 1에 속해면 +1, 클러스터 2에 속하면 -1 이라구 가르치면 될꺼라능.

입력 가중합은 NET는 이렇게 되고

NET = x · w
       = x1*w1 + x2*w2 + x3*w3 ..... xn*wn + b

NET > T인 영역이랑 NET < T인 영역의 경계면은 요렇게 된다능

x1*w1 + x2*w2 + x3*w3 ..... xn*wn + b = 0

어떠냐능. 평면의 방정식 아니냐능. 요게바루 판단면....그러니까 저 빨간선이 되는거심. 그럼 이제 손으로 신경망을 한번 만들어 보자능.


 2차원 패턴 공간에 패턴 4개가 있고 두개로 분류도 있다능. 빨간선은 대충 그어 봤다능.

 입력 페턴
 [ x1 x2 ]
 클러스터
A [ 0    0 ] 0
B [ 1    0 ]  0
C [ 0    1 ] 0
D [ 1    1 ] 1

 보면 알겠지만 AND의 진리표임 >_<. 대충 끄셔놓은 빨간선이 새로축 x2 하고 만나는 값을 1.5라고 하고 가로축 x1하고 만나는 값을 1.5 라고하고 기울기를 -1 이라고 치면.....

x2 = -x1 + 1.5
x1 + x2 - 1.5 = 0


이걸 가지고 신경망을 설계해보면....


요렇게 나온다. 그럼 다음 패턴을 또 해보자. 이번꺼는 XOR의 패턴이라능.


죽어따 깨나도 직선 하나로는 세모랑 네모를 구별할 수 업ㅂ다. 이렇게 직선 하나로 분리가 불가능한 경우를 선형 분리 불가능 linear non-separable 라고 한다. 반면 AND와 같은 경우 처럼 분리가 가능한 경우를 선형 분리 가능 linear separable 이라고 한다능.

 벌써 눈치깠겠지만....단층 신경망은 선형 분리 불가능한 페턴을 분류해 낼 수가 업ㅂ다능. 이 경우에는 신경망을 다층으로만들어서 은닉층에서 원래의 페턴 공간을 선형 분리 가능한 공간으로 맵핑 시킨후에 분리를 해내야 된다능. 이 정도로만 하구 다층신경망 얘기는 나중에 기회가 되면 또 하자능.


퍼셉트론 Preceptron 학습법

 누가 퍼셉트론을 처음 제안 했는지 같은 구질 구질한 역사 얘기는 건너 뛰고.....원래 퍼셉트론은 수용층, 연합층, 반응층3계층으로 구성된 신경망인데 수용층은 별루 하는일이 업ㅂ어서 수용층이랑 연합층을 하나루 합칠수가 있다능. 그래서 생긴건 이렇게생겼다능.


 전에 봤던 그림이라능. 데헷 >_<. 아무튼 퍼셉트론 학습법에는 이진 활성화 함수랑 연속 활성화 함수 둘다를 쓸 수있다능. 초기 연결 강도는 임의의 작은 값으로 설정하면 되구 학습 신호 γ 는 아래 처럼 구할 수 있다능.


 간단하네. 신선함! 목표치 d랑 실제 출력 y의 오차를 학습 신호로 쓸 고 있음. 아무튼 k 단계의 연결 강도 변화량은 아래 처럼 구할 수 있다능.

k+1 단계의 연결 강도는 아래처럼 구하면 된다능.

다 끝났음. 이제 구현하면 된다능 >_<. 구체적인 프로세스는 http://www.filepang.co.kr/entry/퍼셉트론-학습-알고리즘 여기 나와 있으니까 꼭 보라능.

구현

 먼저 NeuralNetwork 라는 이름의 namespace를 하나 열구 클래스를 만들자능. 그리구나서 생성자에서 연결강도를 초기화 하면 되겠심.

namespace NeuralNetwork {
    template<int N, int M>
    class Perceptron{
    public:
        Perceptron(double (*activation_function)(double), double a = 0.1) {
            this->a = a;
            this->activation_function = activation_function;

            for (int i = 0; i < M; i++){
                weights[i].resize(N + 1);
                std::generate_n(weights[i].begin(), N + 1, RandomGenerator(-0.1, 0.1));
            }
        }
    private:
        std::vector<double> weights[M];
        double (*activation_function)(double);
        double a;
    };
}

 N은 입력의 갯수고 M은 뉴런의 갯수라능. a는 학습률 α고 activation_function은 활성함수로 사용할 함수의 함수 포인터라능. 생성자에서 각 뉴런들의 연결강도를 바이어스의 연결강도까지 포함한 N+1개의 랜덤값으로 초기화 해줬다능. RandomGenerator 는 요렇게 생겼심.

namespace NeuralNetwork {
    struct RandomGenerator {
        RandomGenerator(double _min = 0.0, double _max = 0.1) : min(_min), max(_max) {}
        double operator()(void) {
            double random = std::rand() / RAND_MAX;
            return random * (max - min) - min;
        }
        double min, max;
    };
}

T가 0인 양극성 계단 함수도 만들자능.

namespace NeuralNetwork {
    double bipolar_step_function(double x){
        if (x >= 0.0)
            return 1.0;
        return -1.0;
    }
}

이제 신경망의 출력을 구하는 함수를 만들어 보자능.

namespace NeuralNetwork {
    template<int N, int M>
    class Perceptron{
    public:
        template<typename T>
        void recall(T input_begin, T input_end) {
            for (int i = 0; i < M; i++) {
                output_pattern[i] = std::inner_product(weights[i].begin(), weights[i].begin()+N, input_begin, 0.0);
                output_pattern[i] += weights[i][N] * 1.0;

                output_pattern[i] = activation_function(output_pattern[i]);
            }
        }
    public:
        double output_pattern[M];
    };
}

패턴 x를 받아서 가중합을 구하는데...입력에는 바이어스를 포함하지 않아도 되도록 했다능.

output_pattern[i] = std::inner_product(weights[i].begin(), weights[i].begin()+N, input_begin, 0.0);

바어어스를 제외한 가중합을 구하고...

output_pattern[i] += weights[i][N] * 1.0;
output_pattern[i] = activation_function(output_pattern[i]);

바이어스까지 포함시킨후에 출력값을 구했다능. 출력 output_pattern은 getter를 만들기 귀차느니까 public 으로 했다능. 이제 퍼셉트론 학습 방법을 사용해서 학습 시킬는 함수를 만들면 된다능.

namespace NeuralNetwork {
    template<int N, int M>
    class Perceptron{
    public:
        template<typename T>
        double learn(T input_begin, T input_end, T desired_being, T desired_end) {
            recall(input_begin, input_end);                                           
            double error = hamming_distance(output_pattern, output_pattern + M,
                                            desired_being, desired_end);           

            for (int i = 0; i < M; i++) {            
                int j;
                double r = *(desired_being+i) - output_pattern[i];   

                for (j = 0; j < N; j++)
                    weights[i][j] += a * r * *(input_begin+j);       
                weights[i][j] += a * r * 1;                        
            }

            return error;
        }
    };
}

 파라미터로 패턴 x랑 기대하는 값 d를 입력 받았다능. 그리고나서 위에 링크에 있는데로 패턴 x를 입력으로 하는 출력을 구해내고 구해진 출력을 가지고 학습신호 γ를 구했심. γ랑 r이랑 비슷하게 생겼길래 학습 신호의 변수 이름은 r로 했다능.

recall(input_begin, input_end);

 출력을 구해나는 코드고 외부에서 학습이 얼마나 진행됐는지 알 수 있도록 현재의 출력과 기대값과의 오차를 계산해서 리턴하도록 해줬다능. 오차는 해밍 거리를 사용해서 구해냈다능.

double error = hamming_distance(output_pattern, output_pattern + M, desired_being, desired_end);

안에 있는  for문이 실제 학습을 진행 시키는 부분이라능. 출력층의 모든 뉴런들에서 학습 신호를 구해내고 바이어스를 포함한 모든 연결 강도를 변경한다능.

double r = *(desired_being+i) - output_pattern[i];

for (j = 0; j < N; j++)
    weights[i][j] += a * r * *(input_begin+j);
weights[i][j] += a * r * 1;

 마찬 가지로 learn 함수를 사용할때도 입력 패턴에 바이어스를 포함시키지 않도록 했기 때문에....바이어스 연결 강도는 내부 for 문에서 빼내서 따로 구했다능. 저렇게 밖에 못하겠더라능 -_-;;

전체 소스코드랑 OR 게이트의 학습 결과라능.

#include <iostream>
#include <vector>
#include <algorithm>
#include <numeric>
#include <ctime>
#include <cmath>

namespace NeuralNetwork {
    struct RandomGenerator {
        RandomGenerator(double _min = 0.0, double _max = 0.1) : min(_min), max(_max) {}
        double operator()(void) {
            double random = std::rand() / RAND_MAX;
            return random * (max - min) - min;
        }
        double min, max;
    };

    template<typename T>
    double hamming_distance(T input_begin, T input_end, T desired_begin, T desired_end) {
        double distance = 0.0;

        for (; input_begin != input_end && desired_begin != desired_end; ++input_begin, ++desired_begin)
            distance += std::pow(*desired_begin - *input_begin, 2);

        return std::sqrt(distance);
    }

    double bipolar_step_function(double x){
        if (x >= 0.0)
            return 1.0;
        return -1.0;
    }

    double bipolar_sigmoid_function(double x){
        return (1.0 - std::exp(-x)) / (1.0 + std::exp(-x));
    }

    template<int N, int M>
    class Perceptron{
    public:
        Perceptron(double (*activation_function)(double), double a = 0.1) {
            this->a = a;                                            // learning rate
            this->activation_function = activation_function;        // activation functoin

            // initialize weights include bias
            for (int i = 0; i < M; i++){
                weights[i].resize(N + 1);
                std::generate_n(weights[i].begin(), N + 1, RandomGenerator(-0.1, 0.1));
            }

            std::fill(output_pattern, output_pattern + M, 0.0);     // initialize output
        }
        ~Perceptron() {}

        template<typename T>
        void recall(T input_begin, T input_end) {
            for (int i = 0; i < M; i++) {
                output_pattern[i] = std::inner_product(weights[i].begin(), weights[i].begin()+N, input_begin, 0.0);
                output_pattern[i] += weights[i][N] * 1.0;

                output_pattern[i] = activation_function(output_pattern[i]); // compute output
            }
        }

        template<typename T>
        double learn(T input_begin, T input_end, T desired_being, T desired_end) {
            recall(input_begin, input_end);                                            // compute output
            double error = hamming_distance(output_pattern, output_pattern + M,
                                            desired_being, desired_end);            // compute error

            for (int i = 0; i < M; i++) {             // for all neurons in output layer
                int j;
                double r = *(desired_being+i) - output_pattern[i];    // compute learning signal

                for (j = 0; j < N; j++)
                    weights[i][j] += a * r * *(input_begin+j);        // compute delta_w and update weight
                weights[i][j] += a * r * 1;                         // update weight of bias
            }

            return error;
        }

    private:
        std::vector<double> weights[M];
        double (*activation_function)(double);
        double a;

    public:
        double output_pattern[M];
    };
}

int main(void)
{
    using namespace std;
    using namespace NeuralNetwork;

    srand(time(NULL));

    const int n = 2;
    const int m = 1;

    Perceptron<n, m> net(bipolar_step_function, 0.3);

    double input_pattern[4][n] = { {-1.0, -1.0}, {-1.0, 1.0}, {1.0, -1.0}, {1.0, 1.0} };
    double desired_pattern[4][m] = { {-1.0}, {1.0}, {1.0}, {1.0} };

    cout.precision(5);
    cout << showpoint << showpos;
    cout << "before learning...." << endl;

    for (int i = 0; i < 4; i++) {
        net.recall(input_pattern[i], input_pattern[i]+n);

        cout << "    [ ";
        copy(input_pattern[i], input_pattern[i]+n, ostream_iterator<double>(cout, " "));
        cout << "] : ";

        copy(net.output_pattern, net.output_pattern+m, ostream_iterator<double>(cout, " "));
        cout << endl;
    }

    cout << "\\ntraining...." << endl;

    cout << noshowpos;
    for (int i = 0; i < 200; i++) {
        double error = 0.0;

        for (int j = 0; j < 4; j++)
            error += net.learn(input_pattern[j], input_pattern[j]+n,
                                desired_pattern[j], desired_pattern[j]+m);

        cout << "    #"  << i << " : error : " << error << endl;

        if (error == 0.0) {
            cout << "    Traning complete" << endl;
            break;
        }
    }

    cout << "\\nafter learning...." << endl;
    cout << showpos;

    for (int i = 0; i < 4; i++) {
        net.recall(input_pattern[i], input_pattern[i] + n);

        cout << "    [ ";
        copy(input_pattern[i], input_pattern[i]+n, ostream_iterator<double>(cout, " "));
        cout << "] : ";

        copy(net.output_pattern, net.output_pattern+m, ostream_iterator<double>(cout, " "));
        cout << endl;
    }

    return 0;
}

Output
before learning....
    [ -1.0000 -1.0000 ] : -1.0000
    [ -1.0000 +1.0000 ] : +1.0000
    [ +1.0000 -1.0000 ] : +1.0000
    [ +1.0000 +1.0000 ] : +1.0000

training....
    #0 : error : 0.0000
    Traning complete

after learning....
    [ -1.0000 -1.0000 ] : -1.0000
    [ -1.0000 +1.0000 ] : +1.0000
    [ +1.0000 -1.0000 ] : +1.0000
    [ +1.0000 +1.0000 ] : +1.0000

웃기게도 초기연결강도가 분리에 성공했음 -_-;;

---------------------------------------------------------------------------------------------------------------

하일라이트된 소스코드가 보고 싶으면

http://www.filepang.co.kr/entry/단층-신경망

이리로 가라능

추천 비추천

1

고정닉 0

0

원본 첨부파일 1

댓글 영역

전체 댓글 0
본문 보기

하단 갤러리 리스트 영역

왼쪽 컨텐츠 영역

갤러리 리스트 영역

갤러리 리스트
번호 제목 글쓴이 작성일 조회 추천
설문 우리나라를 대표해서 UN 연설자로 내보내고 싶은 스타는? 운영자 25/09/29 - -
AD 프로게이머가 될테야!! 운영자 25/10/01 - -
공지 프로그래밍 갤러리 이용 안내 [96] 운영자 20.09.28 47614 65
2893743 짱깨~ 북괴~ 빨갱이는 대한민국에서 빨리 꺼져랑~ ♥냥덩이♥갤로그로 이동합니다. 16:09 3 0
2893742 정부서버 불낸 책임자 극단자했다는군요 헬마스터갤로그로 이동합니다. 16:09 4 0
2893741 노인개씹버러지새끼들 요즘 100세인생이라고 안해서 좋다 ㅋㅋㅋ [1] 타이밍뒷.통수한방(1.213) 15:32 16 0
2893739 추석 연휴 업소 가는 형들 꿀팁 반값 꿀팁 풀게ㅅㅅㅅ [1] ㅇㅇ(39.7) 15:26 17 0
2893738 좆븅신이 지가 잘난줄 아는 이유 프갤러(210.217) 15:15 26 2
2893737 진짜 개발자가 설명 못하는이유 [1] 프갤러(210.217) 15:11 25 1
2893736 이제 개인용으로 램 64기가정도는 충분히 [9] ㅇㄷ(211.234) 15:00 33 0
2893735 가짜개발자 진짜개발자 구분법 [2] 발명도둑잡기(118.235) 14:58 33 0
2893734 결혼식 갔다왔다 [1] 발명도둑잡기(118.235) 14:57 19 0
2893733 시원하당 ♥냥덩이♥갤로그로 이동합니다. 14:43 17 0
2893731 동생 동영상편집 하고 싶다는데 중고나라에서 30짜리 컴으로 될까?? ㅇㅇ(223.39) 14:17 15 0
2893730 대한민국에 쓰레기들 생각하니까 짱개가 땡기네 프갤러(210.217) 13:41 21 0
2893729 정치가 ㄹㅇ 역겨움 프갤러(210.217) 13:22 25 0
2893728 카카오같은거 보면 개발자들 ㄹㅇ 띨방한 애들밖에 없는듯 [4] 프갤러(210.217) 13:11 67 1
2893727 나는내향적이야 나는조현병이야 손발이시립디다갤로그로 이동합니다. 12:36 27 0
2893725 창업 조언 발명도둑잡기(118.235) 12:23 21 0
2893724 프로그래밍 이야기가 1도 없노 ㅇㅇ(218.157) 12:23 28 0
2893723 신은 왜 쓰레기 같은 새끼한테 시간을 줬을까? 프갤러(210.217) 12:14 32 1
2893722 앱 오버레이 컴포넌트들 다 만들었다 [1] 노력갤로그로 이동합니다. 11:44 34 0
2893721 인공지능, ai 국비하면 취업 가능? [4] cvs.갤로그로 이동합니다. 11:24 64 0
2893720 [이스트소프트] AI 교육받고 제주 자연 속 워케이션 즐기자! [1] [ESTsoft]oreumi-camp(125.183) 10:39 43 1
2893719 뭔지랄을해야 이딴나라에서 태어날수있는거지 [1] 타이밍뒷.통수한방(1.213) 10:35 29 0
2893718 ❤✨☀⭐⚡☘⛩나님 시작합니당⛩☘⚡⭐☀✨❤ ♥냥덩이♥갤로그로 이동합니다. 10:09 30 0
2893717 ❤✨☀⭐⚡☘⛩나님 시작합니당⛩☘⚡⭐☀✨❤ ♥냥덩이♥갤로그로 이동합니다. 09:33 27 0
2893716 수..숨막혀..ㅇㅅㅇ 헤르 미온느갤로그로 이동합니다. 09:31 20 0
2893714 태연 ㅇㅅㅇ 헤르 미온느갤로그로 이동합니다. 09:26 24 0
2893713 하루 한 번 헤르미온느 찬양 헤르 미온느갤로그로 이동합니다. 09:25 31 0
2893712 의정부역 PC방 ㅇㅇ(223.38) 08:40 18 0
2893711 앱공장 해볼만함? 프갤러(180.231) 08:12 25 0
2893692 넥도리아 양념 헌돈 돼지 갈비 추석을 향해 전진. [1] 넥도리아2025(220.74) 06:22 26 0
2893675 음기 충전 발명도둑잡기(118.216) 05:13 51 0
2893673 조심해라 프갤러(211.118) 04:44 45 0
2893671 스포티파이 개인정보 국방부로 팔려나가는 건 시간문제 발명도둑잡기(118.216) 04:16 24 0
2893666 이 패션 진짜 올 가을 유행인가요? 발명도둑잡기(118.235) 04:01 27 0
2893665 스포티파이 인공지능 규제 발표 [1] 발명도둑잡기(118.235) 03:56 32 0
2893663 “엡스타인, 정보기관과 연관됐나” 의혹 여전… 美 정부는 침묵 발명도둑잡기(118.235) 03:36 21 0
2893655 흐름 상징 발명도둑잡기(118.235) 02:54 30 0
2893649 한국 국회, 정부, 법원은 여전히 미군위안부같은 정치를 하고 있다 발명도둑잡기(118.216) 02:42 20 0
2893644 사실 세대론으로 비판하면 안되고 생산수단 가진자를 비판해야 발명도둑잡기(118.235) 01:57 25 0
2893642 오늘의 소설, 영화 실마리: 성매매자 데이터베이스가 외국 정보기관에 발명도둑잡기(118.235) 01:52 17 0
2893641 엠스타인 명단 공개 예정인 의원 발명도둑잡기(118.235) 01:38 21 0
2893639 형님들 스타트업은 원래 조용한가요? [4] ㅇㅇ(106.101) 01:16 83 0
2893638 이직 하고 싶은데 물경력이라 방법이 없다.. [1] ㅇㅇ(175.197) 01:16 39 0
2893637 BTS (방탄소년단) 'Dynamite' 발명도둑잡기(118.216) 01:07 20 0
2893636 먹고 살려고 안해본 일이 없는데, IT 프리랜서 장점은 [1] ㅆㅇㅆ(124.216) 01:06 62 0
2893635 내가 느끼는게 랜딩 페이지 하나 작성에 15만 ㅆㅇㅆ찡갤로그로 이동합니다. 00:59 38 0
2893634 프리로 협업 몇번해봤는데 항상 느끼지만 ㅆㅇㅆ찡갤로그로 이동합니다. 00:56 42 0
2893632 어차피 개발하다보면 서로 지식의 빈곳이 있을수밖에 없어서 [3] ㅆㅇㅆ찡갤로그로 이동합니다. 00:48 67 0
2893631 신해철, 싸이-Dear America [1] 발명도둑잡기(118.216) 00:38 32 0
뉴스 ‘백번의 추억’ 외유내강의 의인화 김다미, 시청자도 반할 수밖에 없었던 순간 3 디시트렌드 10.02
갤러리 내부 검색
제목+내용게시물 정렬 옵션

오른쪽 컨텐츠 영역

실시간 베스트

1/8

뉴스

디시미디어

디시이슈

1/2