발표자: 이활석 (Naver Clova)
발표일: 2017.11.
(현) NAVER Clova Vision
(현) TFKR 운영진
개요:
최근 딥러닝 연구는 지도학습에서 비지도학습으로 급격히 무게 중심이 옮겨지고 있습니다.
특히 컴퓨터 비전 기술 분야에서는 지도학습에 해당하는 이미지 내에 존재하는 정보를 찾는 인식 기술에서,
비지도학습에 해당하는 특정 정보를 담는 이미지를 생성하는 기술인 생성 기술로 연구 동향이 바뀌어 가고 있습니다.
본 세미나에서는 생성 기술의 두 축을 담당하고 있는 VAE(variational autoencoder)와 GAN(generative adversarial network) 동작 원리에 대해서 간략히 살펴 보고, 관련된 주요 논문들의 결과를 공유하고자 합니다.
딥러닝에 대한 지식이 없더라도 생성 모델을 학습할 수 있는 두 방법론인 VAE와 GAN의 개념에 대해 이해하고
그 기술 수준을 파악할 수 있도록 강의 내용을 구성하였습니다.
저는 운 좋게도 게임 PD로서 지난 10년 동안 몇 개의 게임을 개발하고, 서비스하는 경험을 가질 수 있었습니다.
본 세션에서는 제가 그동안 개발했던 게임들을 간단히 돌아보고, 개발 과정에서 시행착오를 통해 배운 것들을 살펴보려고 합니다.
개인적인 경험이라 편향이 있을 수 있겠지만, 게임 PD나 디렉터 커리어를 목표로 하시는 분들께 참고가 될 수 있으면 좋겠습니다.
발표자: 이활석 (Naver Clova)
발표일: 2017.11.
(현) NAVER Clova Vision
(현) TFKR 운영진
개요:
최근 딥러닝 연구는 지도학습에서 비지도학습으로 급격히 무게 중심이 옮겨지고 있습니다.
특히 컴퓨터 비전 기술 분야에서는 지도학습에 해당하는 이미지 내에 존재하는 정보를 찾는 인식 기술에서,
비지도학습에 해당하는 특정 정보를 담는 이미지를 생성하는 기술인 생성 기술로 연구 동향이 바뀌어 가고 있습니다.
본 세미나에서는 생성 기술의 두 축을 담당하고 있는 VAE(variational autoencoder)와 GAN(generative adversarial network) 동작 원리에 대해서 간략히 살펴 보고, 관련된 주요 논문들의 결과를 공유하고자 합니다.
딥러닝에 대한 지식이 없더라도 생성 모델을 학습할 수 있는 두 방법론인 VAE와 GAN의 개념에 대해 이해하고
그 기술 수준을 파악할 수 있도록 강의 내용을 구성하였습니다.
저는 운 좋게도 게임 PD로서 지난 10년 동안 몇 개의 게임을 개발하고, 서비스하는 경험을 가질 수 있었습니다.
본 세션에서는 제가 그동안 개발했던 게임들을 간단히 돌아보고, 개발 과정에서 시행착오를 통해 배운 것들을 살펴보려고 합니다.
개인적인 경험이라 편향이 있을 수 있겠지만, 게임 PD나 디렉터 커리어를 목표로 하시는 분들께 참고가 될 수 있으면 좋겠습니다.
"R을 이용한 데이터 처리 & 분석 실무 - 서민구 지음" 정리 자료 #1
- https://thebook.io/006723/
- 첫번째 : goo.gl/FJjOlq
- 두번째 : goo.gl/Wdb90g
- 세번째 : goo.gl/80VGcn
- 네번째 : goo.gl/lblUsR
[소스 코드]
https://github.com/henlix/data-structure.git
[설명]
대학생 연합 IT 벤처 창업 동아리 S.O.P.T (Shout Our Passion Together - http://sopt.org) 에서 내부적으로 진행하는 전공 과목 기초 스터디 자료입니다.
이번주에 다룰 내용은 전반적인 개요, 복잡도 분석 및 기초 데이터 구조인 배열과 연결리스트 기초입니다.
스터디 자료는 다음과 같은 순서대로 올라갈 예정입니다.
1. 데이터 구조 및 알고리즘
2. 운영체제
3. 네트워크
2. Remarks on Segment Trees
Sogang ICPC Team 1
1–10
1–5 6–10
1–3 4–5 6–8 9–10
1–2 3 4 5 6–7 8 9 10
1 2 6 7
f (x, s, e, · · · ) = f
(
2x, s,
⌊
s + e
2
⌋
, · · ·
)
+ f
(
2x + 1,
⌊
s + e
2
⌋
+ 1, e, · · ·
)
3. Persistent Segment Tree
Sogang ICPC Team 2
T1
1–5
1–3 4–5
1–2 3 4 5
1 2
구조체와 포인터로 구현하며, 2D 쿼리를 처리하기 위해 여러 버전의 트리를 만들 예정
예를 들어 Tn 은 y 좌표가 0 · · · n인 쿼리의 정보를 담는다고 하자
4. Persistent Segment Tree
Sogang ICPC Team 3
T0 T1
1–5
1–3 4–5
1–2 3 4 5
1 2
1–5
1–3 4–5
1–2 3
T2 는 T1 을 기반으로 다른 노드들만 새로 만들고, 나머지 노드들은 포인터로 전 버전의
트리를 가리키게 한다, 이를 반복해 트리 생성
5. Persistent Segment Tree
Sogang ICPC Team 4
총 데이터 수를 n개라 할 때· · ·
✓ 트리 하나 만드는 시간: O (log xmax)
✓ 트리 전체를 만드는 시간: O (n log xmax)
✓ Ti 를 쿼리하는 시간: O (log xmax)
6. Persistent Segment Tree
Sogang ICPC Team 5
R = [xl, xr] × [yl, yr] 쿼리하기?
✓ Tn 은 y 좌표가 0 · · · n인 쿼리의 정보를 담는다
✓ 따라서 R을 쿼리하려면
– Tyr 에 대해서 [xl, xr]을 쿼리
– Tyl−1 에 대해서 [xl, xr]을 쿼리
– 한 후 둘의 차를 구하면 된다
Ti 에 대해 두 번 쿼리하므로 직사각형 영역의 쿼리가 겨우 O (log mx)이다!
7. PSTs vs 2D Segment Trees
Sogang ICPC Team 6
0 ≤ x ≤ mx, 0 ≤ y ≤ my 이고 총 데이터 수를 n개라 할 때· · ·
PST 2D
공간 O (n log mx) O (mxmy)
쿼리 O (log n) O (log mx log my)
8. PSTs vs 2D Segment Trees
Sogang ICPC Team 7
하지만
✓ 값 업데이트
✓ RMQ 처리
같은 일들은 PST가 할 수 없는 부분이고, 값들이 sparse하지 않으면 의미가 별로 없으므로
PST와 2D segment tree 중 적절한 자료구조를 잘 선택해야 한다
9. PSTs vs 2D Segment Trees
Sogang ICPC Team 8
참고: 2D segment tree는 2차원 배열을 이용해 y좌표로 분할 정복 → x좌표로 분할 정복
같은 식으로 만들 수 있다
구현이 생각보다 어렵지 않으니 직접 해 봐도 좋음! (lazy propagation 등 모두 1D
segment tree와 비슷하게 처리하면 된다)
2D segment tree source code
10. Egg #
11012
Sogang ICPC Team 9
당신은 임기가 m일 남은 대통령이고, 매일 유세하러 나간다. 유세는 직사각형 모양의
공간을 돌아다니며 진행한다.
시민들은 집에서 당신이 보이면 달걀을 던진다. 시민들의 집의 좌표들이 주어졌을 때,
유세하러 나가면 몇 개의 달걀을 맞을지 구하라.
✓ 집 개수 = n ≤ 10000, m ≤ 50000
✓ 0 ≤ x, y ≤ 105
✓ 테스트 케이스 20개
11. Egg #
11012
Sogang ICPC Team 10
문제를 간단히 하면
✓ R = [xl, xr] × [yl, yr] 내부의 점의 개수를 세는 쿼리를 구현해라
가 된다
13. Egg #
11012
Sogang ICPC Team 12
35 int init(int s, int e) {
36 if (s == e) {
37 nodes.emplace_back(0);
38 } else {
39 int m = (s + e) / 2;
40 int l = init(s, m), r = init(m + 1, e);
41 nodes.emplace_back(l, r, 0);
42 }
43 return nodes.size() - 1;
44 }
source code
그냥 세그먼트 트리 만들듯이
14. Egg #
11012
Sogang ICPC Team 13
46 int _sum(int x, int s, int e, int l, int r) {
47 pst_node u = nodes[x];
48 if (l > r) return 0;
49 if (e < l || r < s) return 0;
50 if (l <= s && e <= r) return u.sum;
51 int m = (s + e) / 2;
52 return _sum(u.l, s, m, l, r)
53 + _sum(u.r, m + 1, e, l, r);
54 }
source code
그냥 세그먼트 트리 만들듯이
15. Egg #
11012
Sogang ICPC Team 14
56 int _add(int x, int s, int e, int i, int dv) {
57 pst_node u = nodes[x];
58 if (s == e) {
59 nodes.emplace_back(u.sum + dv);
60 } else {
61 int m = (s + e) / 2;
62 if (i <= m) {
63 int l = _add(u.l, s, m, i, dv);
64 nodes.emplace_back(l, u.r, u.sum + dv);
65 } else {
66 int r = _add(u.r, m + 1, e, i, dv);
67 nodes.emplace_back(u.l, r, u.sum + dv);
68 }
69 }
70 return nodes.size() - 1;
71 }
source code
여기서는 갱신되는 부분만 새로 만들어준다
16. Egg #
11012
Sogang ICPC Team 15
86 void add_back() {
87 root_indexes.emplace_back(root_indexes.back());
88 }
source code
트리 버전 업 – root_indexes에는 버전마다 루트의 인덱스들이 들어 있음
17. Egg #
11012
Sogang ICPC Team 16
101 priority_queue<pii, vector<pii>, greater<>> coords;
102 while (n--) {
103 int x, y;
104 cin >> x >> y;
105 coords.emplace(x, y);
106 }
source code
좌표 입력
18. Egg #
11012
Sogang ICPC Team 17
108 pst tree(100000);
109 for (int i = 0; i <= 100000; i++) {
110 while (coords.size() && coords.top().first == i) {
111 tree.update_back(coords.top().second, 1);
112 coords.pop();
113 }
114 tree.add_back();
115 }
source code
PST 생성
19. Egg #
11012
Sogang ICPC Team 18
117 int s = 0;
118 while (q--) {
119 int l, r, b, t;
120 cin >> l >> r >> b >> t;
121
122 s += tree.sum(b, t, l, r);
123 }
124 cout << s << 'n';
source code
쿼리 처리
20. Egg #
11012
Sogang ICPC Team 19
73 int sum(int xl, int xr, int y) {
74 return _sum(root_indexes[y], 0, xn, xl, xr);
75 }
76
77 int sum(int xl, int xr, int yl, int yr) {
78 if (yl <= 0) return sum(xl, xr, yr);
79 return sum(xl, xr, yr) - sum(xl, xr, yl - 1);
80 }
source code
쿼리 처리
21. PST로 더 할 수 있는 것
Sogang ICPC Team 20
✓ 구간에서 k번째 원소 구하기
– 원소의 값들을 좌표 압축하고 구간 내에서 이분 탐색
✓ 물론 이 트리도 HLD와 섞을 수 있다
22. K번째 수 #
7469
Sogang ICPC Team 21
✓ Q (i, j, k): 배열 a [i · · · j]를 정렬했을 때, k번째 수를 리턴하는 함수
를 구현해라
23. K번째 수 #
7469
Sogang ICPC Team 22
Q (i, j, k): 배열 a [i · · · j]를 정렬했을 때, k번째 수를 리턴하는 함수
✓ 배열에 저장된 정수의 값들을 좌표 압축 하듯이 압축하고
– zip : a [i] = v → v′
✓ 인덱스를 i, 압축된 값을 v′
라고 했을 때 배열의 원소 각각을
(
v′
, i
)
라는 점들로
생각한다면
✓ [0, x] × [i, j]에 속한 점의 개수가 k개가 되는 x를 찾으면 된다
24. K번째 수 #
7469
Sogang ICPC Team 23
[0, x] × [i, j]에 속한 점의 개수가 k개가 되는 x를 찾으면 된다
✓ PST의 경우 기본적으로 [xa, xb] × [0, y]의 쿼리를 처리하므로
✓
(
[0, x] × [0, j] 에 속한 점의 개수
)
−
(
[0, x] × [0, i − 1] 에 속한 점의 개수
)
를 계산
– 인덱스 트리 쓰듯이
– 쿼리 한 번에 O (log xmax)
25. K번째 수 #
7469
Sogang ICPC Team 24
82 int _kth(int yli, int yri, int s, int e, int k) {
83 if (s == e) return s;
84 int p = nodes[nodes[yri].l].sum - nodes[nodes[yli].l].sum;
85 if (k < p) {
86 return _kth(nodes[yli].l, nodes[yri].l, s, (s + e) / 2, k);
87 } else {
88 return _kth(nodes[yli].r, nodes[yri].r, (s + e) / 2 + 1, e, k - p);
89 }
90 }
91
92 int kth(int yl, int yr, int k) {
93 return _kth(root_indexes[yl - 1], root_indexes[yr], 0, xn, k);
94 }
source code
26. K번째 수 #
7469
Sogang ICPC Team 25
116 for (int i = 0; i < n; i++) {
117 cin >> a[i];
118 zip[a[i]] = 1;
119 }
120
121 int c = 1;
122 for (const auto& kv : zip) {
123 int i = kv.first;
124 zip[i] = c;
125 unzip[c] = i;
126 c++;
127 }
source code
27. K번째 수 #
7469
Sogang ICPC Team 26
129 pst tree(100000);
130
131 for (int i = 0; i < n; i++) { // (x, y) = (v', i)
132 tree.add_back();
133 tree.update_back(zip[a[i]], 1);
134 }
source code
(
v′
, i
)
임에 주의
28. K번째 수 #
7469
Sogang ICPC Team 27
136 while (m--) {
137 int i, j, k;
138 cin >> i >> j >> k;
139 cout << unzip[tree.kth(i, j, k - 1)] << 'n';
140 }
source code
29. 4회차 연습문제
Sogang ICPC Team 28
✓ Egg #
11012
✓ K번째 수 #
7469
1. 수열과 쿼리 22 #
16978
2. 트리와 쿼리 8 #
13517 = 트리와 K번째 수 #
11932
3. XOR 쿼리 #
13538
4. 히스토그램에서 가장 큰 직사각형과 쿼리 #
16977