Posts
All the articles I've posted.
| 이름 | (몸무게, 키) | 덩치 등수 |
|---|---|---|
| A | (55, 185) | 2 |
| B | (58, 183) | 2 |
| C | (88, 186) | 1 |
| D | (60, 175) | 2 |
| E | (46, 155) | 5 |
위 표에서 C보다 더 큰 덩치의 사람이 없으므로 C는 1등이 된다. 그리고 A, B, D 각각의 덩치보다 큰 사람은 C뿐이므로 이들은 모두 2등이 된다. 그리고 E보다 큰 덩치는 A, B, C, D 이렇게 4명이므로 E의 덩치는 5등이 된다. 위 경우에 3등과 4등은 존재하지 않는다. 여러분은 학생 N명의 몸무게와 키가 담긴 입력을 읽어서 각 사람의 덩치 등수를 계산하여 출력해야 한다.
첫 줄에는 전체 사람의 수 N이 주어진다. 그리고 이어지는 N개의 줄에는 각 사람의 몸무게와 키를 나타내는 양의 정수 x와 y가 하나의 공백을 두고 각각 나타난다.
여러분은 입력에 나열된 사람의 덩치 등수를 구해서 그 순서대로 첫 줄에 출력해야 한다. 단, 각 덩치 등수는 공백문자로 분리되어야 한다.
덩치
백준 7568번 '덩치' (실버 5) 문제 풀이. implementation, bruteforcing 로 접근했다.
merge_sort(A[p..r]) { # A[p..r]을 오름차순 정렬한다.
if (p < r) then {
q <- ⌊(p + r) / 2⌋; # q는 p, r의 중간 지점
merge_sort(A, p, q); # 전반부 정렬
merge_sort(A, q + 1, r); # 후반부 정렬
merge(A, p, q, r); # 병합
}
}
# A[p..q]와 A[q+1..r]을 병합하여 A[p..r]을 오름차순 정렬된 상태로 만든다.
# A[p..q]와 A[q+1..r]은 이미 오름차순으로 정렬되어 있다.
merge(A[], p, q, r) {
i <- p; j <- q + 1; t <- 1;
while (i ≤ q and j ≤ r) {
if (A[i] ≤ A[j])
then tmp[t++] <- A[i++]; # tmp[t] <- A[i]; t++; i++;
else tmp[t++] <- A[j++]; # tmp[t] <- A[j]; t++; j++;
}
while (i ≤ q) # 왼쪽 배열 부분이 남은 경우
tmp[t++] <- A[i++];
while (j ≤ r) # 오른쪽 배열 부분이 남은 경우
tmp[t++] <- A[j++];
i <- p; t <- 1;
while (i ≤ r) # 결과를 A[p..r]에 저장
A[i++] <- tmp[t++];
}병합 정렬 1
백준 24060번 '병합 정렬 1' (실버 3) 문제 풀이. implementation, sort, recursion 로 접근했다.
| 시간 제한 | 메모리 제한 |
|---|---|
| 0.3 | 512 |
한 줄로 된 간단한 에디터를 구현하려고 한다. 이 편집기는 영어 소문자만을 기록할 수 있는 편집기로, 최대 600,000글자까지 입력할 수 있다.
이 편집기에는 ‘커서’라는 것이 있는데, 커서는 문장의 맨 앞(첫 번째 문자의 왼쪽), 문장의 맨 뒤(마지막 문자의 오른쪽), 또는 문장 중간 임의의 곳(모든 연속된 두 문자 사이)에 위치할 수 있다. 즉 길이가 L인 문자열이 현재 편집기에 입력되어 있으면, 커서가 위치할 수 있는 곳은 L+1가지 경우가 있다.
이 편집기가 지원하는 명령어는 다음과 같다.
| L | 커서를 왼쪽으로 한 칸 옮김 (커서가 문장의 맨 앞이면 무시됨) |
|---|---|
| D | 커서를 오른쪽으로 한 칸 옮김 (커서가 문장의 맨 뒤이면 무시됨) |
| B | 커서 왼쪽에 있는 문자를 삭제함 (커서가 문장의 맨 앞이면 무시됨)삭제로 인해 커서는 한 칸 왼쪽으로 이동한 것처럼 나타나지만, 실제로 커서의 오른쪽에 있던 문자는 그대로임 |
| P $ | $라는 문자를 커서 왼쪽에 추가함 |
에디터
백준 1406번 '에디터' (실버 2) 문제 풀이. data structures, stack, linked list 로 접근했다.
nums = {1 : [1],
2 : [2, 4, 8, 6],
3 : [3, 9, 7, 1],
4 : [4, 6],
5 : [5],
6 : [6],
7 : [7, 9, 3, 1],
8 : [8, 4, 2, 6],
9 : [9, 1]}
for _ in range(n):
a, b = map(int, input().split())
# a의 1의 자리수를 구한다 -> 4
one = a % 10
# 1의 자리에 나올 수 있는 값들을 가져온다 -> nums[4] -> [4, 6]
# 이 중에서 b번째 값을 취한다. 4, 6, 4, 6, 4, 6 -> 6
print(nums[one][(b - 1) % len(nums[one])])
단 a의 1의 자리가 0일 경우 무조건 제곱한 수의 1의 자리도 0이므로 10번 컴퓨터가 처리하게 된다.
분산 처리
백준 1009번 '분산 처리' (브론즈 2) 문제 풀이. math, implementation 로 접근했다.
| 종류 | 점수 함수 | Q의 출처 | K, V의 출처 | 출처 논문 |
|---|---|---|---|---|
| Bahdanau (additive) | decoder 직전 상태 | encoder 전체 | Bahdanau et al. (2015) | |
| Luong dot | decoder 현재 상태 | encoder 전체 | Luong et al. (2015) | |
| Luong general | decoder 현재 상태 | encoder 전체 | Luong et al. (2015) | |
| Luong concat | decoder 현재 상태 | encoder 전체 | Luong et al. (2015) | |
| Encoder self-attention | encoder 이전 층 | encoder 이전 층 | Vaswani et al. (2017) | |
| Masked self-attention | (뒤쪽 ) | decoder 이전 층 | decoder 이전 층 | Vaswani et al. (2017) |
| Encoder-decoder attention | decoder 이전 층 | encoder 출력 | Vaswani et al. (2017) |
Attention 메커니즘 정리 - Seq2Seq에서 Transformer까지
Lab11-5에서 Seq2Seq model을 공부하면서 입력 문장 전체를 vector 하나로 압축한다는 점이 계속 걸렸다.
def evaluate(pairs, source_vocab, target_vocab, encoder, decoder, target_max_length):
for pair in pairs:
print(">", pair[0])
print("=", pair[1])
source_tensor = tensorize(source_vocab, pair[0])
source_length = source_tensor.size()[0]
encoder_hidden = torch.zeros([1, 1, encoder.hidden_size]).to(device)
for ei in range(source_length):
_, encoder_hidden = encoder(source_tensor[ei], encoder_hidden)
decoder_input = torch.Tensor([[SOS_token]]).long().to(device) # 수정해야 작동
decoder_hidden = encoder_hidden
decoded_words = []
for di in range(target_max_length):
decoder_output, decoder_hidden = decoder(decoder_input, decoder_hidden)
_, top_index = decoder_output.data.topk(1) # 1개의 가장 큰 요소를 반환
if top_index.item() == EOS_token:
decoded_words.append("<EOS>")
break
else:
decoded_words.append(target_vocab.index2vocab[top_index.item()])
decoder_input = top_index.squeeze().detach()
predict_words = decoded_words
predict_sentence = " ".join(predict_words)
print("<", predict_sentence)
print("")Seq2Seq
Seq2Seq model은 아래와 같은 구조를 가지고 있다. 일종의 Encoder-Decoder 구조라고도 할 수 있는데 모든 입력을 다 받은 후에 출력을 생성하는 구조이다.
# load data
xy = np.loadtxt("data-02-stock_daily.csv", delimiter=",")
xy = xy[::-1] # reverse order
# split train-test set
train_size = int(len(xy) * 0.7)
train_set = xy[0:train_size]
test_set = xy[train_size - seq_length:]
앞서 언급한대로 scaling을 하고 학습하기 좋은 형태로 data를 가공해야 한다.
def minmax_scaler(data):
numerator = data - np.min(data, 0)
denominator = np.max(data, 0) - np.min(data, 0)
return numerator / (denominator + 1e-7)
train_set = minmax_scaler(train_set)
test_set = minmax_scaler(test_set)Timeseries
timeseries(시게열) data는 일정 시간 간격으로 배치된 data를 말한다. 매장의 시간별 매출, 요일별 주식 시가/종가 등이 여기에 속할 수 있다.
# data setting
x_data = []
y_data = []
# window를 오른쪽으로 움직이면서 자름
for i in range(0, len(sentence) - sequence_length):
x_str = sentence[i:i + sequence_length]
y_str = sentence[i + 1: i + sequence_length + 1]
print(i, x_str, '->', y_str)
x_data.append([char_dic[c] for c in x_str]) # x str to index (dict 사용)
y_data.append([char_dic[c] for c in y_str]) # y str to index
x_one_hot = [np.eye(dic_size)[x] for x in x_data]
X = torch.FloatTensor(x_one_hot)
Y = torch.LongTensor(y_data)
'''output
0 if you wan -> f you want
1 f you want -> you want
2 you want -> you want t
3 you want t -> ou want to
4 ou want to -> u want to
...
166 ty of the -> y of the s
167 y of the s -> of the se
168 of the se -> of the sea
169 of the sea -> f the sea.
'''RNN - longseq
앞서 살펴보았던 RNN 예제들은 모두 한 단어나 짧은 문장에 대해 RNN을 학습시키는 내용들이었다. 하지만 우리가 다루고 싶은 데이터는 더 긴 문장이거나 내용을 가질 가능성이 높다.
char_set = ['h', 'i', 'e', 'l', 'o']
# hyper parameters
input_size = len(char_set)
hidden_size = len(char_set)
learning_rate = 0.1
# data setting
x_data = [[0, 1, 0, 2, 3, 3]]
x_one_hot = [[[1, 0, 0, 0, 0],
[0, 1, 0, 0, 0],
[1, 0, 0, 0, 0],
[0, 0, 1, 0, 0],
[0, 0, 0, 1, 0],
[0, 0, 0, 1, 0]]]
y_data = [[1, 0, 2, 3, 3, 4]]
X = torch.FloatTensor(x_one_hot)
Y = torch.LongTensor(y_data)
마찬가지로 one-hot encoding하여 Tensor로 바꾼다. 다만 각 알파벳 변수에 배열을 저장하는 방식이 아니라 char_set에 저장된 알파벳을 x_data의 값을 인덱스로 불러오는 방식이다.
one-hot encoding은 x_data에 적용하여 학습한다.
RNN - hihello / charseq
hihello 문제는 같은 문자들이 다음 문자가 다른 경우 이를 예측하는 문제를 말한다. hihello에서 'h'와 'l'은 2번씩 등장하지만 어디에 문자가 위치하느냐에 따라 다음에 올 문자가 달라진다.