티스토리 뷰
- SASRec 모델을 변형해보는 식으로 미니 프로젝트를 진행했고, 그 중에서 나는 Position Embedding 방식을 고치는 역할을 맡았다!
- Position Embedding 과 Positional Encoding 관련해서 연구하면서 척척학사정도 된 것 같은데 이 내용을 정리해보도록 하겠다.
원래 SASRec의 Position Embedding
Self-Attention에서는 위치정보를 알 수 있는 정보가 없기에 SASRec 모델에 학습가능한 Position Embedding Vector을 더해줌!
처음에 maxlen 크기만큼 0~ maxlen까지 순차적인 값을 가지도록 설정되어 있는 걸 nn.Embedding을 이용해 임베딩 벡터로 바꿔주고 역전파를 통해서 이 임베딩 벡터가 갱신됨!
position 정보를 고정값이 아닌 parameter로서 가지면서 학습을 통해 포지션끼리의 거리 관계 정보를 유추하게 된다!
positions = np.tile(np.array(range(log_seqs.shape[1])), [log_seqs.shape[0], 1])
"""maxlen = 50일때, 다음과 같이 설정됨
[[ 0 1 2 ... 47 48 49]
[ 0 1 2 ... 47 48 49]
[ 0 1 2 ... 47 48 49]
...
[ 0 1 2 ... 47 48 49]
[ 0 1 2 ... 47 48 49]
[ 0 1 2 ... 47 48 49]]
"""
seqs += self.pos_emb(torch.LongTensor(positions).to(self.dev)) # position embedding - (batch_size * max_len *d) 크기, 아이템 임베딩이랑 더해짐
"""# cf) self.pos_emb = torch.nn.Embedding(args.maxlen, args.hidden_units) nn.Embedding에 태우면
[
[ -0.51, 0.46, -0.15, -1.70, 0.47, -0.30, -1.86, 0.87 ],
[ -1.00, -0.44, 1.08, -0.31, 0.00, 0.32, 0.89, -2.33 ],
[ -0.41, 0.48, 1.15, 0.88, 0.70, -1.44, -1.20, -1.74 ],
[ 1.50, 1.86, -1.07, 0.61, 0.17, 0.28, 0.06, -0.65 ],
[ 0.32, -0.02, 0.64, -1.61, -0.11, -0.29, -0.54, -0.72 ],
[ -0.26, -0.46, 0.01, -0.94, -2.22, -0.09, 0.39, -0.37 ],
[ -0.19, -1.34, -0.83, -0.25, 0.20, 0.81, -1.66, -2.10 ],
[ 1.30, -0.79, -0.13, 0.23, -0.70, -0.15, 0.79, 1.04 ],
[ 0.06, 1.26, 0.69, 0.40, 1.16, 0.23, -1.68, 0.18 ],
[ 1.44, -0.81, 2.69, 0.28, -0.63, -0.27, 1.23, -0.65 ],
[ 2.07, 0.24, -1.21, -1.10, -1.22, 1.72, -0.69, -0.61 ],
[ -0.08, 0.41, -1.18, -0.50, -1.05, 1.54, -1.10, -1.07 ],
[ 0.35, -0.79, -0.69, 1.02, -0.82, -1.47, 2.20, 0.94 ],
] 요런식으로 임베딩 됨 - 이 경우는 maxlen이13이고, hidden unit가 8인 경우
"""
시도1. Position Embedding 대신 Sinusoidal positional Encoding 사용
- SASRec 모델이 기본적으로 Transformer의 Self-Attention 구조와 매우 유사하므로, <Attention Is All You Need> 에 등장하는 Positional Encoding 방식을 사용해봄.
- 앞선, position embedding의 경우 학습되는 파라미터로, 역전파 과정에서 임베딩 벡터가 갱신되었다면, Sinusodial positional encoding 방식은 파라미터가 아닌 고정된 position embedding vector로 모델 학습 시 갱신되지 않음!
- Sinusoidal Positional Encoding은 포지션끼리 가까우면 내적이 커지고 멀면 내적이 작아져서 내적으로부터 거리관계를 유추!
SASRec 변형 코드
# PositionalEncoding class 정의해줌
class PositionalEncoding(torch.nn.Module):
def __init__(self, hidden_units, max_len):
super().__init__()
# Positional Encoding 초기화
# (max_len,hidden_units) 크기의 tensor생성
self.P_E = torch.zeros(max_len, hidden_units)
# 학습되는 파라미터가 아니므로 requires_grad 을 False로 설정
self.P_E.requires_grad = False
# pos (0~max_len) 생성 (row 방향 => unsqueeze(dim=1))
pos = torch.arange(0, max_len, dtype=torch.float).unsqueeze(dim=1)
# _2i (0~2i) 생성 (col 방향)
# 2i는 step = 2 를 활용하여 i의 2배수를 만듦
_2i = torch.arange(0, hidden_units, step= 2, dtype=torch.float)
# sinusodial positional encoding 생성 - 짝수일땐 sin / 홀수 일땐 cos
self.P_E[:, 0::2] = torch.sin(pos / 10000 ** (_2i / hidden_units))
self.P_E[:, 1::2] = torch.cos(pos / 10000 ** (_2i / hidden_units))
def forward(self,x):
# x seq 길이에 맞춰 PE return
# (seq_len, hidden_units)
batch_size, seq_len = x.size()
PE_for_x = self.P_E[:seq_len,:]
return PE_for_x
- <Attention Is All You Need> 논문에서 둘 중 어느 방법을 사용하든지 비슷한 성능이라고 하는데, 여기서도 마찬가지였다!
- 기존 : NDCG@10 = 0.6048, HR@10 : 0.8509
- 시도1: NDCG@10= 0.6047 , HR@10 : 0.8432
시도2. Position Embedding 초기화 시, Random한 값으로 초기화
- 기존 SASRec의 position embedding은 [ 0 1 2 ... 47 48 49] 와 같이 0~ maxlen까지 오름차순으로 증가하는 값을 가지도록 초기화됨
- 이 초기화된 값은 역전파를 통해서 계속해서 갱신되는데, 어차피 갱신되는 값이므로 이를 랜덤값으로 초기화 시켜보자라는 시도!
- 최근 논문에서 딥러닝에 들어가는 행렬을 랜덤 초기화했을 때 가장 좋은 성능을 얻을 수 있다고 들어서 이러한 방법을 시도해보았고, 일반화 능력이 올라가지 않을까해서 도전해봄
positions = np.random.permutation(np.arange(log_seqs.shape[1]))
positions = np.tile(positions, (log_seqs.shape[0], 1))
seqs += self.pos_emb(torch.LongTensor(positions).to(self.dev)) # position embedding - (batch_size * max_len *d) 크기, 아이템 임베딩이랑 더해짐
- 하지만 그 결과, 비슷한 성능 보여줌!
- 기존 : NDCG@10 = 0.6048, HR@10 : 0.8509
- 시도2: NDCG@10= 0.6040 , HR@10 : 0.8458
'RecSys' 카테고리의 다른 글
[RecSys] Sequential Recommendation (0) | 2023.09.24 |
---|---|
[RecSys] 3. Matrix Factorization (0) | 2023.09.17 |
[RecSys] 2. 컨텐츠 기반 필터링과 협업 필터링 (1) | 2023.08.29 |
[RecSys] 1. 추천시스템 개념 및 고전 추천 알고리즘 (0) | 2023.08.29 |
[RecSys] SASRec 코드 리뷰 (0) | 2023.07.12 |
- Total
- Today
- Yesterday
- 연관규칙분석
- rag 다중문서 활용
- ORDER BY LIMIT
- 알고리즘
- NULL AS
- reranker 속도 개선
- treer구조
- 서브쿼리
- cold-start
- Lagrange Multipler
- llm reranker
- pointwise reranker
- WHERE문 집계함수
- 이코테
- 여러개 값에 대한 조작
- SQL레시피
- SET문
- SQL
- NULL인 열 만들어주기
- SASRec
- 숨겨진조건
- SELECT문 안 서브쿼리
- WHERE절서브쿼리
- groupby 다중
- 추천시스템
- 하이브리드 필터링
- reranker
- 하나의 테이블에 대한 조작
- 고전적 추천 알고리즘
- 다중 GROUP BY
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | ||
6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 | 14 | 15 | 16 | 17 | 18 | 19 |
20 | 21 | 22 | 23 | 24 | 25 | 26 |
27 | 28 | 29 | 30 |