[ GPT 요약 ]
이 논문의 주된 의의 : 주기적 활성화 함수 ( 사인 함수 ) 를 이용하여 암시적 표현을 처리하는 새로운 방식을 제안
기존의 ReLU (기존의 활성화 함수) 기반 신경망은 세밀한 정보나 미분을 잘 표현하지 못한다.
그러나 이 부분들은 자연 신호( 오디오, 이미지)의 표현이나 편미분 방정식(PDE)를 풀때 매우 중요한 요소
SIREN은 주기적 활성화 함수를 사용함으로써 이 한계를 극복하여, 복잡한 신호와 그 미분을 매우 고품질로 표현 가능
특히 이미지 및 동영상 표현, 3D 모델링, 그리고 경계값 문제 해결 ( Poisson 방정식, Helmholtz 방정식 등)에 매우 효과적
[ 리마인드 ]
< 활성화 함수 >
정의 : 퍼셉트론에서 가중합을 처리해서 다음 층으로 내보낼 때 쓰는 함수
기계학습 수업에서는 계단함수, ReLU등을 사용했다.
1) ReLU 대신 사인 함수를 쓰면 세밀한 정보를 표현하고 미분 값을 정교하게 표현하는 것이 가능하다.
2) 따라서 물리학에서 나오는 복잡한 편미분 방정식 문제들을 잘 다룰 수 있다.
< "높은 주파수 성분 == 세밀한 정보"의 의미 >
1) 주파수라는 것은 시간이나 공간에 따라 신호가 얼마나 빠르게 변하는지를 나타낸다.
2) 주파수가 높다는 것은 신호가 매우 빠르게 변화한다는 뜻
3) 예를들어 이미지에서 높은 주파수 성분은 경계선이나 작은 세부 묘사처럼 아주 세밀하고 급격한 변화를 뜻한다.
4) 낮은 주파수 성분은 큰 패턴이나 전체적인 색상변화 같은 느린변화를 뜻한다.
[ Abstract ]
"신경망으로 매개변수화된 암시적으로 정의된, 연속적이며 미분 가능한 신호 표현은 강력한 패러다임으로 부상하고 있으며, 기존 표현 방식에 비해 많은 잠재적 이점을 제공합니다.
그러나 이러한 암시적 신경 표현을 위한 현재의 네트워크 아키텍처는 신호의 세밀한 부분을 모델링할 수 없으며, 공간적 및 시간적 미분을 표현하지 못합니다. 이는 많은 물리적 신호가 편미분 방정식의 해로서 암시적으로 정의된다는 사실에도 불구하고 중요한 요소입니다.
우리는 이러한 암시적 신경 표현을 위해 주기적 활성화 함수를 활용하는 방법을 제안하며, 이러한 네트워크를 SIREN(사인 함수 기반 신경망)이라 부르고, 복잡한 자연 신호와 그 미분을 표현하는 데 매우 적합함을 입증합니다.
우리는 SIREN의 활성화 통계를 분석하여 원칙적인 초기화 방안을 제안하고, 이미지, 파동장, 비디오, 소리 및 그 미분을 표현하는 데 SIREN이 활용될 수 있음을 보여줍니다.
더 나아가, 우리는 SIREN이 특정한 경계값 문제, 예를 들어 Eikonal 방정식(서명 거리 함수 생성), Poisson 방정식, Helmholtz 및 파동 방정식과 같은 어려운 문제들을 해결하는 데 활용될 수 있음을 보여줍니다.
마지막으로, 우리는 SIREN을 하이퍼네트워크와 결합하여 SIREN 함수 공간에 대한 사전 지식을 학습할 수 있음을 입증합니다.
제안된 방법 및 모든 응용 분야에 대한 비디오 개요는 프로젝트 웹사이트에서 확인할 수 있습니다."
1) 현재 상황 : INR 방식의 도입
2) 문제점 : 세밀한 부분이나 성능의 한계
3) 해결첵 제시 : 활성화함수로 사인함수를 도입함으로써 성능을 개선
4) 여러가지 부분에서 성능 입증
[ 1. Introduction ]
저자들이 관심을 가지고 있는 함수들의 집합은 아래의 수식을 만족하는 것들이다.
1) 왼쪽 식F는 함수와 그 함수의 도함수 그리고 여러번 미분된 함수들 간의 관계를 나타내므로 미분방정식이다.
2) 즉 우리의 목표는 미분방정식의 꼴을 하고 있는 문제의 형태에 부합하는 함수를 찾는 것이다.
< 1번째 문단 >
" 이 암시적 문제는 공간적 또는 시공간적 좌표 x ∈ Rm를 입력으로 받아, 선택적으로 이러한 좌표에 대한 Φ의 미분값을 포함합니다.
우리의 목표는 Φ를 매개변수화하여 x를 특정 관심 값으로 매핑하면서 (1)번 방정식에서 제시한 제약을 만족하는 신경망을 학습하는 것입니다. 따라서, Φ는 F에 의해 암시적으로 정의된 관계에 의해 정의되며, 우리는 이러한 암시적으로 정의된 함수들을 매개변수화하는 신경망을 암시적 신경 표현(implicit neural representations)이라 부릅니다.
이 논문에서 설명하듯이, 과학적 분야에서 다양한 문제들이 이 형태에 해당합니다. 예를 들어, 이미지, 비디오, 오디오 처리에서 연속적이고 미분 가능한 표현을 사용하여 다양한 이산 신호들을 모델링하는 것, 서명 거리 함수(signed distance functions)를 통해 3D 형태를 학습하는 것[1–4], 더 일반적으로는 Poisson 방정식, Helmholtz 방정식, 파동 방정식과 같은 경계값 문제를 해결하는 것입니다. "
1) 라는 함수 : 공간이나 시간좌표 ( x ) 를 입력으로 받아서 어떤 결과 값을 반환하는 함수
2) 암시적 문제 : 함수 Φ가 직접적으로 정의되지 않고, 방정식을 만족하는 형태로만 정의되기 때문에 암시적 문제라고 부른다.
3) 목표 : 신경망을 사용해서 함수 Φ를 찾아내는 것
4) INR : 위의 주어진 방정식을 만족하면서, 주어진 좌표 x에 대해 우리가 원하는 값을 찾아낼 수 있는 함수를 구하는 신경망을 INR 정의
5) 쓰임 : 위에서 말한 다양한 과학적 문제들이 위 형태에 해당
< 2번째 문단 >
"연속적인 매개변수화는 이산적인 그리드 기반 표현에 비해 여러 가지 이점을 제공합니다. 예를 들어, Φ가 x의 연속적인 영역에서 정의되기 때문에, 이산적인 표현보다 훨씬 더 메모리 효율적일 수 있으며, 그리드 해상도의 한계가 아닌 신경망 아키텍처의 용량에 따라 세밀한 디테일을 모델링할 수 있습니다. 미분 가능하다는 것은, 자동 미분을 사용하여 기울기(gradient)와 고차 미분을 분석적으로 계산할 수 있다는 것을 의미하며, 이는 이러한 모델들이 기존의 그리드 해상도에 의존하지 않게 해줍니다. 마지막으로, 미분이 잘 정의되어 있다는 것은 암시적 신경 표현이 미분 방정식과 같은 역문제를 해결할 수 있는 새로운 도구를 제공할 수 있음을 의미합니다."
1) 메모리 효율적임 : 그리드 (픽셀 방식 )처럼 모든 지점을 일일이 저장할 필요가 없다.
2) 해상도 자유로움 : 연속적인 방식은 고정된 그리드 방식이 아니라 해상도를 바꾸어가면서 표현 가능
-> 연속적인 함수에서 값을 끌어오니깐 더 세밀하게 입력값을 넣어도 모두 출력가능
3) 미분 가능하다는 것 : 자동으로 미분하여 . 그함수의 변화율이나 더 고차 미분 계산이 가능핟.
4) 다른 문제로의 확장 : 미분이 잘 되는 신경망은 물리학이나 수학에서 쓰는 방정식을 풀 때 융용한 방법이 될 수 있다.
< 3번째 문단 >
"이러한 이유들로 인해, 암시적 신경 표현(implicit neural representations)은 지난 1년 동안 상당한 연구 관심을 받아왔습니다(2장에서 설명). 최근 대부분의 이러한 신경 표현은 ReLU 기반의 다층 퍼셉트론(MLP)을 기반으로 하고 있습니다. 이러한 구조는 유망하지만, 기본 신호에서 세밀한 디테일을 표현하는 능력이 부족하며, 목표 신호의 미분을 잘 표현하지 못합니다. 이는 부분적으로 ReLU 네트워크가 구간별 선형적이기 때문인데, 그 결과 2차 미분이 모든 곳에서 0이 되며, 자연 신호에 포함된 고차 미분 정보(더 복잡한 변화율)를 모델링할 수 없게 됩니다. tanh나 softplus와 같은 대체 활성화 함수들은 고차 미분을 표현할 수 있지만, 우리는 이들의 미분이 종종 잘 정의되지 않으며, 세밀한 디테일을 표현하는 데에도 실패한다는 것을 보여줍니다."
1) 이때까지의 신경표현은 ReLU기반의 MLP를 사용
2) ReLU는 세밀한 디테일을 표현하는 능력이 부족하며, 목표 신호의 미분을 잘 표현하지 못한다.
-> 그 이유는 2차 미분시 모든곳에서 0이 돼서, 자연 신호에 포함된 고차미분 정보를 표현할 수 없기 때문
3) tanh나 softplus같은 활성함수는 고차 미분을 표현하지만, 종종 미분이 잘 정의되지 않고 세밀한 디테일을 표현하는데 실패
< 4번째 문단 >.
"이러한 한계를 해결하기 위해, 우리는 암시적 신경 표현을 위해 주기적 활성화 함수를 가진 MLP(다층 퍼셉트론)를 사용합니다. 우리는 이 접근 방식이 ReLU 기반 MLP나 동시대 연구에서 제안된 위치 인코딩 전략보다 신호의 세부 정보를 더 잘 표현할 수 있을 뿐만 아니라, 이러한 특성이 신호의 미분에도 고유하게 적용된다는 것을 입증합니다. 이는 우리가 이 논문에서 다루는 많은 응용 분야에서 매우 중요한 요소입니다."
1) 위에 나왔던 ReLU기반의 MLP의 한계를 극복하기 위한 해결책으로 "주기적 활성화 함수를 가진 MLP"를 사용
2) "주기적 활성화 함수를 가진 MLP"는 신호 세부정보를 더 잘 표한 할 수 있고, 신호의 미분에도 고유하게 적용. ---> 논문의 가장 중요한 요소
< Summarize >
"
- 주기적 활성화 함수를 사용하는 연속적 암시적 신경 표현을 통해 자연 이미지나 3D 형태와 같은 복잡한 신호와 그 미분을 강건하게 적합하는 방법.
- 이러한 표현을 훈련하기 위한 초기화 방안과, 하이퍼네트워크를 사용해 이러한 표현의 분포를 학습할 수 있음을 검증.
- 이미지, 비디오, 오디오 표현, 3D 형태 재구성, 신호의 기울기만을 이용해 신호를 추정하는 1차 미분 방정식 해결, 2차 미분 방정식 해결과 같은 응용 사례 시연.
"
1) 이 논문에서 제시할 것들을 요약해서 보여주고 있다.
[ 2. Related Work ]
1)이 논의 배경이 되는 논문들을 주석과 함께 설명하는 부분
< 1번째 문단 >
"Implicit Nueral Representations : 암시적 신경 표현. 최근 연구는 완전 연결 신경망이 모양의 부분, 객체, 또는 장면에 대해 연속적이고 메모리 효율적인 암시적 표현으로서의 잠재력을 가지고 있음을 입증했습니다.
이러한 표현들은 일반적으로 서명 거리 함수(signed distance functions) 또는 점유 네트워크(occupancy networks) 형태의 3D 데이터로부터 훈련됩니다.
형태를 표현하는 것 외에도, 이러한 모델 중 일부는 객체의 외형을 인코딩하도록 확장되었으며, 이는 다중 뷰 2D 이미지 데이터를 사용한 신경 렌더링(neural rendering)을 통해 훈련될 수 있습니다.
시간적 정보를 고려한 확장 모델들과, 객체의 부분별로 의미적 분할(semantic segmentation)을 추가한 변형 모델도 제안되었습니다."
1) INR에서 fully connected layer가 연속적이고 메모리 효율적인 암시적 표현으로 뛰어나다는 것을 다시 한번 강조
2) INR은 3D데이터를 입력으로 받아서 훈련될 수 있다. 그 데이터를 표현하는 함수는 서명 거리 함수나 점유 네트워크등이 있다.
-> 서명 거리 함수 ( signed distance functions ) : 어떤점이 물체의 표면에서 얼마나 떨어졌는지 알려주는 함수
표면. : 값이. 0.
물체 안 : 값이 음수
물체 밖 : 값이 양수
-> 점유 네트워크 ( Occupancy Networks ) : 공간의 각 점이 물체의 내부에 있는지 아닌지를 0과 1로 나타낸다.
3) 객체의 외형을 인코딩 : 일부 모델은 객체의 외형을 생성해서 표현하기도 한다.
-> 이때 여러 각도에서 본 2D 이미지를 활용해서 학습할 수도 있다.
4) 시간정보나 객체의 부분별 의미적 분할을 한 변형 모델등의 다양한 확장 모델도 제안됨
=> 전체적으로, INR 방식이 연구되고 확장되어 온 과정을 설명한다.
< 2번째 문단 >
"주기적 비선형성. 주기적 비선형성은 지난 몇십 년 동안 여러 차례 연구되어 왔지만, 아직까지는 대안적인 활성화 함수들보다 안정적으로 더 좋은 성능을 보여주지 못했습니다.
초기 연구에는 단일 은닉층 신경망을 통해 푸리에 변환을 모방하도록 설계된 푸리에 신경망이 포함됩니다 [20, 21].
다른 연구에서는 주기적 활성화를 사용한 신경망을 단순한 분류 작업과 순환 신경망에 적용하는 연구들이 있었습니다 [22–24] [25–29].
이러한 모델들은 보편적 함수 근사(universal function approximation) 특성을 가진다고 입증되었습니다 [30–32].
구성적 패턴 생성 네트워크(Compositional pattern producing networks) 역시 주기적 비선형성을 활용하지만, 이는 유전 알고리즘 프레임워크를 통해 서로 다른 비선형성을 결합하는 방식을 사용합니다 [33, 34].
**이산 코사인 변환(Discrete Cosine Transform)에서 영감을 받은 Klocek 등의 연구에서는 이미지 표현을 위해 코사인 활성화 함수를 활용했지만, 그 연구에서는 이 표현의 미분이나 다른 응용 사례에 대해서는 연구하지 않았습니다 [35].
이러한 선행 연구들에 영감을 받아, 우리는 암시적 신경 표현 및 그 미분을 포함한 응용 분야에 대해 주기적 활성화 함수를 사용하는 MLP(다층 퍼셉트론)를 탐구하고, 이를 위한 원칙적인 초기화 및 일반화 방법을 제안합니다."
1) 활성함수로 주기적 비선형적 함수를 사용한 이전의 영감을 받은 사례들에 대해 설명한다.
2) 푸리에 신경망이나 다른 연구들에 대해 설명
3) 위 주기적 활성화 함수를 사용한 신경망들은 "보편적 함수 근사 특성"을 가진다고 입증
-> 보편적 함수 근사 특성 : 어떤 함수든 신경망을 사용하여 충분히 정확하게 근사할 수 있다
=> 이후에도 영감을 받은 다른 모델을을 제시
1) 제일 왼쪽 Ground Truth 이미지를 학습하여 오른쪽 각각 다른 활성화 함수를 사용해서 복원한 이미지
2) 2번째, 3번째 열에는 도함수와 이계도함수를 사용한 이미지까지 나타내었다.
3) 여기서 SIREN(sin함수를 활성함수로 사용한 모델)의 경우 도함수와 이계도함수까지도 거의 완벽하게 복원해낸다.
4) PSNR( Peak Signal-to-Noise Ratio) 최대 신호 대 잡음비 : 이미지나 영상 품질을 평가하는 지표 -> SIREN이 학습이 반복될수록 월등하게 좋다.
***** 질문 ***** : 여기서 Ground Truth는 단순히 원본 이미지인데 원본 이미지를 미분한다는 개념은 무엇인가요?
-> 미분 방정식 풀이 내용은 나중에
[ 3 Formulation ]
{ 3.1 Periodic Activations for Implicit Neural Representations }
< 1번째 문단 >
"
암시적 신경 표현을 위한 주기적 활성화 함수
우리는 사인 함수를 주기적 활성화 함수로 사용하는 암시적 신경 표현을 위한 간단한 신경망 아키텍처인 SIREN을 제안합니다:
1) 표현식은 i번째 레이어에 관한 것이다.
2) 이 표현식은 가중치 행렬 W와 b를 이용해서 입력값 x를 변환하는 affine(아핀) 변환을 수행한다.
3) 이렇게 변환되어 출력된 출력벡터에 활성화함수 ( 사인함수 )를 적용시킨다.
< 2번째 문단 >
"흥미롭게도, SIREN의 미분은 그 자체로도 SIREN입니다.
이는 사인의 미분이 코사인, 즉 위상이 이동된 사인 함수이기 때문입니다(추가 자료 참조).
따라서, SIREN의 미분도 SIREN의 특성을 이어받아, 복잡한 신호에 대해 SIREN의 미분을 지도할 수 있습니다.
우리의 실험에서, SIREN이 i의 미분을 포함하는 제약 조건 Cm을 사용해 지도될 때도, 함수 ϕ는 여전히 잘 동작함을 보여줍니다.
이는 경계값 문제(BVP)와 같은 많은 문제를 해결하는 데 중요한 요소입니다."
1) sin 함수는 미분해도 sin(cos의 평행이동)이 된다.
2) 따라서 미분이 아주 용이해진다.
3) 따라서 미분이 필요한 문제상황에서도 매우 잘 동작한다.
4) 그래서 경계값 문제등을 해결하기 좋다.
< 3번째 문단 >
"우리는 SIREN이 활성화 분포를 어느 정도 제어하면서 초기화될 수 있음을 보여줄 것입니다.
이를 통해 깊은 신경망 아키텍처를 만들 수 있습니다.
더 나아가, SIREN은 기본 아키텍처들보다 훨씬 더 빠르게 수렴하며, 예를 들어, 단일 이미지를 몇 백 번의 반복만으로 적합시킬 수 있고, 최신 GPU에서는 몇 초 만에 처리되며, 더 높은 이미지 품질을 제공합니다(Fig. 1 참조)."
1) 활성화 분포를 제어한다는 것: 사인 함수와 같은 활성화 함수가 신경망 내애서 어떻게 동작할지, 그 범위나 출력을 조절 가능하다는것
2) 신경망이 깊어질수록 복잡한 패턴이나 데이터를 학습할 수 있지만 동시에 학습이 어려워질수도 있다.
SIREN은 이러한 깊은 신경망을 초기화할떄도 활성화 함수가 적절하게 동작하도록 제어할 수 있기 떄문에, 깊은 신경망도 효과적으로 학습
< 간단한 예제 : 이미지에 적합시키기 >
[ 첫 문단 ]
"유일한 제약 조건 C는 가 픽셀 좌표에서 이미지 색상 값을 출력해야 한다는 것입니다.
이는 의 미분과는 관련이 없으며, 오직 Φ와 f(xi)에만 의존합니다.
이 제약 조건은 다음과 같이 표현됩니다:C(f(xi),Φ(x))=Φ(xi)−f(xi)
이는 손실 함수로 변환되어 다음과 같이 표현할 수 있습니다: L ̃ = i ∥Φ(xi) − f(xi)∥^2 "
1)
3) 동영상에 대해서도 실험 수행 -> ReLU보다 좋은 성능
{ 3.2 Distribution of activations, frequencies, and a principled initialization scheme }
활성화, 주파수 분포 및 체계적인 초기화 방식
[ 첫 문단 ]
"
우리는 SIRENs(신경망)의 효과적인 학습을 위해 필요한 체계적인 초기화 방식을 제시합니다.
여기서는 비공식적으로 설명하지만, 더 자세한 내용과 증명, 실험적 검증은 부록에서 다룹니다.
우리의 초기화 방식의 핵심 아이디어는 네트워크를 통해 활성화 분포를 보존하여, 초기화 시 최종 출력이 레이어 수에 의존하지 않도록 하는 것입니다.
주의할 점은, 균일하게 분포된 가중치를 신중하게 선택하지 않고 SIRENs를 구성할 경우, 정확도와 수렴 속도 모두에서 성능이 저하된다는 것입니다.
"
1) 효과적인 학습을 위한 초기화 방식 제안
2) 활성화 값 : 활성함수가 적용된 다음 층으로 넘기는 값
-> 이 값들이 지나치게 커지거나 작아지면 학습이 어려워진다. 그래서 초기화 단계에서 잘 처리해야 층이 많아져도 문제가 안생긴다 -> *P1*
3) 이렇게 안하면 성능이 떨어진다.
< *P1* >
신경망(Neural Network)은 여러 층(layer)으로 이루어진 구조입니다. 각 층은 입력값을 받아 계산을 한 후, 다음 층으로 전달하는 방식으로 작동합니다. 이때 중요한 것은, 각 층을 통과하는 값들이 적절하게 유지되어야 한다는 점입니다. 만약 값들이 층을 통과하면서 점점 커지거나 작아지면, 신경망이 학습하기 어려워집니다. 이런 문제는 주로 층이 많을수록 심각해지는데, 이걸 "기울기 소실(Vanishing Gradient)"이나 "기울기 폭발(Exploding Gradient)"이라고 부릅니다.
- 기울기 소실(Vanishing Gradient): 층을 많이 거치면서 값이 점점 작아져 0에 가까워지는 현상입니다. 값이 너무 작아지면, 신경망은 더 이상 제대로 학습할 수 없게 됩니다. 계산이 거의 안 일어나게 되죠.
- 기울기 폭발(Exploding Gradient): 반대로 값이 점점 커지면, 학습이 불안정해지고 결과가 엉뚱해질 수 있습니다. 값이 너무 커져서 계산에 문제가 생기는 거죠.
이 문제를 해결하기 위해 초기화 방식이 매우 중요합니다. 초기화 방식은 신경망의 가중치를 처음 설정하는 방법인데, 잘못 초기화하면 값들이 층을 거치면서 너무 작아지거나 커지게 됩니다. 좋은 초기화 방식은 처음부터 각 층에서 나오는 값들이 고르게 분포되어, 학습이 시작될 때부터 안정적으로 진행되도록 합니다.
1) 요약하면 초기값을 잘 설정해야만 값들이 층을 넘어가면서 점점 이상해지지 않는다!
2) 초기화를 잘못하면 층이 많아질수록 학습이 잘 안 되는 문제가 생기기 때문에, 층의 개수와 관계없이 신호가 잘 흐를 수 있도록 처음부터 값을 잘 설정하는 것이 매우 중요!
[ 둘째 문단 ]
"
우선, 입력이 x ∼ U(−1, 1)로 균일 분포된 단일 사인 뉴런의 출력 분포를 고려해봅시다.
이 뉴런의 출력은 y = sin(ax + b)이고, 여기서 a와 b는 실수입니다.
a > π/2, 즉 사인 함수가 최소한 반주기를 포함하는 경우, 사인의 출력 y는 arcsine(−1, 1) 분포를 따릅니다. 이 arcsine 분포는 U형 베타 분포의 특수한 경우이며, b의 선택과는 독립적입니다. 이제 뉴런의 출력 분포에 대해 논의할 수 있습니다. n개의 입력 x ∈ Rn의 선형 결합에 가중치 w ∈ Rn를 곱하면, 출력은 y = sin(w^T x + b)입니다. 이 뉴런이 두 번째 층에 있다고 가정하면, 각 입력은 아크사인 분포를 따릅니다. 가중치의 각 요소가 wi ∼ U(−c/√n, c/√n)처럼 균일하게 분포한다고 가정할 때, 우리는 w^T x의 내적이 n이 증가함에 따라 정규 분포 w^T x ∼ N(0, c^2/6)로 수렴한다는 것을 보여줍니다(부록 참조). 마지막으로, 이 정규 분포된 내적을 다시 사인 함수에 넣으면, c > √6인 경우 그 출력은 다시 아크사인 분포를 따릅니다. SIREN의 가중치는 각도로 해석될 수 있으며, 편향(bias)은 위상 오프셋으로 해석될 수 있다는 점에 주목하십시오. 따라서 가중치의 크기가 클수록 네트워크에 더 큰 주파수가 나타납니다. 만약 |w^T x| < π/4인 경우, 사인 함수는 주파수를 그대로 유지하는데, 이는 사인 함수가 해당 구간에서 거의 선형이기 때문입니다. 실제로 우리는 |w^T x| < π와 같은 크기에서는 사인 층이 공간 주파수를 대체로 일정하게 유지하고, 이 값을 초과하는 진폭에서는 공간 주파수를 증가시킨다는 것을 실험적으로 발견했습니다. "
[ 코드 ]
import torch
from torch import nn
import torch.nn.functional as F
from torch.utils.data import DataLoader, Dataset
import os
from PIL import Image
from torchvision.transforms import Resize, Compose, ToTensor, Normalize
import numpy as np
import skimage
import matplotlib.pyplot as plt
import time
def get_mgrid(sidelen, dim=2):
'''Generates a flattened grid of (x,y,...) coordinates in a range of -1 to 1.
sidelen: int
dim: int'''
tensors = tuple(dim * [torch.linspace(-1, 1, steps=sidelen)])
mgrid = torch.stack(torch.meshgrid(*tensors), dim=-1)
mgrid = mgrid.reshape(-1, dim)
return mgrid
1) 이미지나 데이터를 처리할 때 좌표 그리드를 생성하는 함수인 get_mgrid를 정의
2) 주요 기능은 좌표 그리드를 생성하여 신경망 학습에서 사용할 수 있게 해줍니다.
3) 256 x 256으로 sidelen을 설정하면, 그렇게 나눈다.
class SineLayer(nn.Module):
# See paper sec. 3.2, final paragraph, and supplement Sec. 1.5 for discussion of omega_0.
# If is_first=True, omega_0 is a frequency factor which simply multiplies the activations before the
# nonlinearity. Different signals may require different omega_0 in the first layer - this is a
# hyperparameter.
# If is_first=False, then the weights will be divided by omega_0 so as to keep the magnitude of
# activations constant, but boost gradients to the weight matrix (see supplement Sec. 1.5)
def __init__(self, in_features, out_features, bias=True,
is_first=False, omega_0=30):
super().__init__()
self.omega_0 = omega_0
self.is_first = is_first
self.in_features = in_features
self.linear = nn.Linear(in_features, out_features, bias=bias)
self.init_weights()
def init_weights(self):
with torch.no_grad():
if self.is_first:
self.linear.weight.uniform_(-1 / self.in_features,
1 / self.in_features)
else:
self.linear.weight.uniform_(-np.sqrt(6 / self.in_features) / self.omega_0,
np.sqrt(6 / self.in_features) / self.omega_0)
def forward(self, input):
return torch.sin(self.omega_0 * self.linear(input))
def forward_with_intermediate(self, input):
# For visualization of activation distributions
intermediate = self.omega_0 * self.linear(input)
return torch.sin(intermediate), intermediate
1) **SineLayer**는 사인 함수를 활성화 함수로 사용하는 신경망 계층입니다.
2) 이 계층은 선형 변환을 수행한 후, 그 결과에 사인 함수를 적용하여 출력합니다.
3_****는 활성화 함수를 조정하여 신호의 주파수를 변경할 수 있는 하이퍼파라미터입니다.
class Siren(nn.Module):
def __init__(self, in_features, hidden_features, hidden_layers, out_features, outermost_linear=False,
first_omega_0=30, hidden_omega_0=30.):
super().__init__()
self.net = []
self.net.append(SineLayer(in_features, hidden_features,
is_first=True, omega_0=first_omega_0))
for i in range(hidden_layers):
self.net.append(SineLayer(hidden_features, hidden_features,
is_first=False, omega_0=hidden_omega_0))
if outermost_linear:
final_linear = nn.Linear(hidden_features, out_features)
with torch.no_grad():
final_linear.weight.uniform_(-np.sqrt(6 / hidden_features) / hidden_omega_0,
np.sqrt(6 / hidden_features) / hidden_omega_0)
self.net.append(final_linear)
else:
self.net.append(SineLayer(hidden_features, out_features,
is_first=False, omega_0=hidden_omega_0))
self.net = nn.Sequential(*self.net)
def forward(self, coords):
coords = coords.clone().detach().requires_grad_(True) # allows to take derivative w.r.t. input
output = self.net(coords)
return output, coords
def forward_with_activations(self, coords, retain_grad=False):
'''Returns not only model output, but also intermediate activations.
Only used for visualizing activations later!'''
activations = OrderedDict()
activation_count = 0
x = coords.clone().detach().requires_grad_(True)
activations['input'] = x
for i, layer in enumerate(self.net):
if isinstance(layer, SineLayer):
x, intermed = layer.forward_with_intermediate(x)
if retain_grad:
x.retain_grad()
intermed.retain_grad()
activations['_'.join((str(layer.__class__), "%d" % activation_count))] = intermed
activation_count += 1
else:
x = layer(x)
if retain_grad:
x.retain_grad()
activations['_'.join((str(layer.__class__), "%d" % activation_count))] = x
activation_count += 1
return activations
1) Siren 클래스는 사인 함수를 활성화 함수로 사용하는 신경망입니다.
2)입력 좌표에 대해 신경망이 출력을 계산하며, 필요시 중간 활성화 값도 반환할 수 있습니다.
3) **forward**는 순전파를 수행하고, **forward_with_activations**는 중간 결과(활성화 값)를 추적하는 기능이 있습니다
def laplace(y, x):
grad = gradient(y, x)
return divergence(grad, x)
def divergence(y, x):
div = 0.
for i in range(y.shape[-1]):
div += torch.autograd.grad(y[..., i], x, torch.ones_like(y[..., i]), create_graph=True)[0][..., i:i+1]
return div
def gradient(y, x, grad_outputs=None):
if grad_outputs is None:
grad_outputs = torch.ones_like(y)
grad = torch.autograd.grad(y, [x], grad_outputs=grad_outputs, create_graph=True)[0]
return grad
1) 라플라시안(Laplacian), 발산(Divergence), 그리고 기울기(Gradient)**를 계산하는 함수들을 정의
def get_cameraman_tensor(sidelength):
img = Image.fromarray(skimage.data.camera())
transform = Compose([
Resize(sidelength),
ToTensor(),
Normalize(torch.Tensor([0.5]), torch.Tensor([0.5]))
])
img = transform(img)
return img
1) 카메라맨 이미지를 가져와서 PyTorch 텐서로 변환하는 함수입니다. 주로 이미지를 신경망에 입력으로 사용하기 위해 전처리하는 과정
{ 이미지 fitting 과정 }
class ImageFitting(Dataset):
def __init__(self, sidelength):
super().__init__()
img = get_cameraman_tensor(sidelength)
self.pixels = img.permute(1, 2, 0).view(-1, 1)
self.coords = get_mgrid(sidelength, 2)
def __len__(self):
return 1
def __getitem__(self, idx):
if idx > 0: raise IndexError
return self.coords, self.pixels
1) 이 코드는 PyTorch의 Dataset 클래스를 상속하여 이미지 학습을 위한 데이터셋을 정의한 것입니다. 이 클래스는 카메라맨 이미지의 픽셀 값과 해당 픽셀의 좌표를 제공하며, 이를 신경망에 학습시킬 수 있도록 준비합니다.
cameraman = ImageFitting(256)
dataloader = DataLoader(cameraman, batch_size=1, pin_memory=True, num_workers=0)
img_siren = Siren(in_features=2, out_features=1, hidden_features=256,
hidden_layers=3, outermost_linear=True)
img_siren.cuda()
total_steps = 500 # Since the whole image is our dataset, this just means 500 gradient descent steps.
steps_til_summary = 10
optim = torch.optim.Adam(lr=1e-4, params=img_siren.parameters())
model_input, ground_truth = next(iter(dataloader))
model_input, ground_truth = model_input.cuda(), ground_truth.cuda()
for step in range(total_steps):
model_output, coords = img_siren(model_input)
loss = ((model_output - ground_truth)**2).mean()
if not step % steps_til_summary:
print("Step %d, Total loss %0.6f" % (step, loss))
img_grad = gradient(model_output, coords)
img_laplacian = laplace(model_output, coords)
fig, axes = plt.subplots(1,3, figsize=(18,6))
axes[0].imshow(model_output.cpu().view(256,256).detach().numpy())
axes[1].imshow(img_grad.norm(dim=-1).cpu().view(256,256).detach().numpy())
axes[2].imshow(img_laplacian.cpu().view(256,256).detach().numpy())
plt.show()
optim.zero_grad()
loss.backward()
optim.step()
1)SIREN 모델을 사용하여 카메라맨 이미지를 학습시키고, 학습 과정에서 **출력, 기울기(gradient), 라플라시안(laplacian)**을 시각화하는
'학부연구 MLVC LAB' 카테고리의 다른 글
Deep Compression 논문 리뷰 (0) | 2025.01.24 |
---|---|
3D Gaussian Splatting Code Run (0) | 2025.01.06 |
3D Gaussian Splatting 논문 리뷰 (0) | 2024.11.05 |
AIM 2024 Sparse Neural Rendering Challenge:Dataset and Benchmark (0) | 2024.09.29 |
Distillation - 개념 (0) | 2024.09.13 |