Published on

πŸ‘©β€πŸ’» | λ°”λ‹₯λΆ€ν„° λ„μ „ν•˜λŠ” λͺ¨μ…˜ 생성: Autoencoder편

이번 ν¬μŠ€νŒ…μ—μ„œ μ°Έκ³ ν•΄μ„œ λͺ¨λΈμ„ λ§Œλ“  논문은 μ•„λž˜μ™€ κ°™λ‹€.

Data Acquisition & Preprocessing

λ³Έ λ…Όλ¬Έμ—μ„œ λ°μ΄ν„°λŠ” λͺ¨λ“  CMU mocap dataλ₯Ό μ‚¬μš©ν•˜μ˜€λ‹€. μ „λ°˜μ μΈ μ „μ²˜λ¦¬ 과정은

  1. 120(cmu 기본 fps) -> 30fps둜 sub-sample
  2. 80 frame을 κ²Ήμ³μ„œ 160 frameμ”© μž˜λΌμ„œ 데이터λ₯Ό λ§Œλ“¦
  3. joint length μ •κ·œν™”
  4. joint듀을 μ€‘μš”ν•œ 20개둜 μ€„μ—¬μ„œ μ‚¬μš©
  5. globalμ—μ„œ local position으둜 transform ν•΄μ„œ μ‚¬μš©
    • local position = Global position - Root XZ position
    • YRotation도 제거
  6. YμΆ• κΈ°μ€€ κ°μ†λ„λŠ” μΊλ¦­ν„°μ˜ μ•ž λ°©ν–₯ κΈ°μ€€μœΌλ‘œ 계산
  7. 60개(= 20*3)의 정보 λ’€μ—λŠ” Root XZ 속도와 Y각속도 정보λ₯Ό μΆ”κ°€λ‘œ 63개의 정보가 λ“€μ–΄κ°„λ‹€λ‹€

λ”°λΌμ„œ λ°μ΄ν„°μ˜ ν˜•νƒœλŠ” X∈R160Γ—63\begin{aligned} X \in R^{160 \times 63} \end{aligned}와 κ°™λ‹€.

각 데이터 λ³„λ‘œ 뼈의 길이가 제각기라 μ •κ·œν™” 과정을 κ±°μ³€λŠ”λ°, 이 뢀뢄은 μ €μžμ˜ μ‚¬μ΄νŠΈμ—μ„œ ꡬ할 수 μžˆλ‹€.

κ·Έλž˜μ„œ μœ„ κ³Όμ •μ—μ„œ 3λ²ˆμ€ μƒλž΅ν•  수 μžˆμ—ˆλ‹€.

μ‚¬μš©ν•œ μ „μ²˜λ¦¬μš© λΌμ΄λΈŒλŸ¬λ¦¬λ‘œλŠ” pymoλ₯Ό μ‚¬μš©ν–ˆλ‹€.

μ•ˆνƒ€κΉκ²Œλ„ μ›μ €μž‘μžκ°€ ꡉμž₯히 였래 λ°©μΉ˜λ˜μ–΄μ„œ μ‚¬λžŒλ“€μ΄ forkν•΄μ„œ μ“΄ 버전듀이 λ§Žλ‹€. 본인은 μ•„λž˜ simon λ²„μ „μ—μ„œ 자체적으둜 μ „μ²˜λ¦¬μ— 맞게 νŒŒμ΄ν”„λΌμΈμ„ λ§Œλ“€μ—ˆλ‹€. μ•„λž˜μ™€ 같이 μ „μ²˜λ¦¬λ₯Ό ν•  수 μžˆμ—ˆλ‹€..!

parser = BVHParser()
parsed_data = parser.parse(filepath)

data_pipe = Pipeline(
    [
        ("param", MocapParameterizer("position")),
        ("jtsel", JointSelector(JOINTS, include_root=False)),
        ("dwnsampl", DownSampler(tgt_fps=30, keep_all=False)),
        ("globrm", GlobalMotionRemover()), # Custom template
        ("np", Numpyfier()),
    ]
)
piped_data = data_pipe.fit_transform([parsed_data])
slicer = Slicer(window_size=160, overlap=0.5)
piped_data = slicer.fit_transform(piped_data)

μ΅œμ’…μ μœΌλ‘œλŠ” (9721, 160, 63)와 같은 shape을 κ°€μ§„λ‹€.

Convolutional Autoencoder

keras둜 λ§Œλ“€μ—ˆκ³  λͺ¨λΈμ˜ summaryλŠ” μ•„λž˜μ™€ κ°™λ‹€. μ•„λ¬΄λž˜λ„ μƒˆλ‘œμš΄ λͺ¨μ…˜ 자체 생성이라기 λ³΄λ‹€λŠ” manifold 생성이 포컀슀라고 보면 λ˜κ² λ‹€. inputκ³Ό output λ™μΌν•˜κ²Œ μ•½ 5초 κ°€λŸ‰μ˜ window 정보가 λ“€μ–΄κ°€κ³  λ‚˜μ˜¨λ‹€.

┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━┓
┃ Layer (type)                         ┃ Output Shape                ┃         Param # ┃
┑━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━┩
β”‚ input_layer (InputLayer)             β”‚ (None, 160, 63)             β”‚               0 β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ conv1d (Conv1D)                      β”‚ (None, 160, 64)             β”‚          60,544 β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ max_pooling1d (MaxPooling1D)         β”‚ (None, 80, 64)              β”‚               0 β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ activation (Activation)              β”‚ (None, 80, 64)              β”‚               0 β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ conv1d_1 (Conv1D)                    β”‚ (None, 80, 128)             β”‚         123,008 β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ max_pooling1d_1 (MaxPooling1D)       β”‚ (None, 40, 128)             β”‚               0 β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ activation_1 (Activation)            β”‚ (None, 40, 128)             β”‚               0 β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ conv1d_2 (Conv1D)                    β”‚ (None, 40, 256)             β”‚         491,776 β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ max_pooling1d_2 (MaxPooling1D)       β”‚ (None, 20, 256)             β”‚               0 β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ activation_2 (Activation)            β”‚ (None, 20, 256)             β”‚               0 β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ functional_1 (Functional)            β”‚ (None, 160, 63)             β”‚         675,135 β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
 Total params: 1,350,463 (5.15 MB)
 Trainable params: 1,350,463 (5.15 MB)
 Non-trainable params: 0 (0.00 B)

Train

논문에 적힌 ν•˜μ΄νŒŒλΌλ―Έν„° λͺ‡ κ°€μ§€λ‘œ ν›ˆλ ¨ν–ˆμ„ λ•Œ ν›ˆλ ¨μ΄ 진행이 μ•ˆλ˜κ³  ν„°μ§€λŠ” λ¬Έμ œκ°€ μžˆμ—ˆλ‹€.

Learning decayμ—μ„œ μ΄ˆκΉƒκ°’μ„ 0.5μ—μ„œ 0.001둜, decay 값을 0.9 μ—μ„œ 0.95둜 μˆ˜μ •ν•˜μ˜€λ‹€. 그리고 ν›ˆλ ¨ν•˜κΈ° 전에 z-score normalization으둜 μ •κ·œν™”λ₯Ό 거치고 ν›ˆλ ¨μ„ ν•˜μ˜€λ‹€. κ·Έ μ™ΈλŠ” λ…Όλ¬Έκ³Ό μ΅œλŒ€ν•œ λ™μΌν•˜κ²Œ κ΅¬ν˜„ν•˜λ €κ³  λ…Έλ ₯ν–ˆλ‹€. GeForce RTX 5060μ—μ„œ ν›ˆλ ¨ μ‹œκ°„μ€ μ•½ 6뢄이 μ†Œμš”λ˜μ—ˆμœΌλ©° fitting μ‹œκ°„μ€ 3뢄이 μ†Œμš”λ˜μ—ˆλ‹€. λ…Όλ¬Έμ—μ„œ 적힌 5μ‹œκ°„μ˜ ν›ˆλ ¨ μ‹œκ°„μ„ μƒκ°ν•˜λ©΄ ν•˜λ“œμ›¨μ–΄μ˜ λ°œμ „μ΄ κ·Ό 10λ…„λ™μ•ˆ 많이 μžˆμ—ˆλ‹€λŠ” 것도 체감할 수 μžˆμ—ˆλ‹€..

Learning rateTotal Loss
epoch_learning_rateepoch_loss

Result

Manifoldκ°€ ν•™μŠ΅λ˜μ–΄μ„œ μ£Όμ–΄μ§„ 데이터가 μ£Όμ–΄μ‘Œμ„ λ•Œ 잘 μˆ˜ν–‰ν•˜λŠ” λͺ¨μŠ΅μ„ μ•„λž˜μ™€ 같이 μ•Œ 수 μžˆλ‹€

Sampled Index 1Sampled Index 2
Figure 1Figure 2

Code

μ½”λ“œλŠ” μ΅œλŒ€ν•œ μ •λ¦¬ν•΄μ„œ μ•„λž˜ 리포지터리에 λ‚¨κ²¨λ†“μ•˜λ‹€.

Authors