안녕하세요? 오랫만에 스터디 글을 써보겠습니다. 오늘의 주제는 '메모리'입니다.


생성모델에서 언어모델이건 이미지모델이건, 뭔가 모델이 '알고' 있는 내용을 바탕으로 만들어내는 것은 분명해보입니다. 그리고 파인튜닝을 통해서 그 내용에 영향을 줄 수 있는 것도 직접 확인해 볼 수 있습니다.


혹자는 파인튜닝은 기존의 베이스 모델이 알고 있던 정보의 형태를 정렬하는 것만 가능할 뿐, 새로운 지식을 추가하는 것은 아니다라고 주장하는 경우도 있는데요, 몇몇 사례를 놓고 이러한 주장이 맞는지 틀린지에 대해서는 단언할 수가 없습니다. 왜냐하면 추가 학습하는 데이타셋의 크기, 학습시간, 모델의 형태, LoRA의 경우 랭크나 학습률, 대상 모듈 등의 하이퍼파라메터, 파운데이션 모델 자체의 과적합 여부 등,  여러가지 요소가 영향을 끼치기 때문이지요. 


이런 부분에 대해서는 딥러닝 모델의 원리를 알아야 각각의 정황정보를 해석할 수 있고, 올바른 판단을 내릴 수 있겠죠.


그래서 오늘 시간에는 어찌보면 가장 흥미로운 주제라고도 할 수 있는 딥러닝 모델의 '기억' 에 대한 얘기를 해보려고 합니다.


https://www.youtube.com/watch?v=piF6D6CQxUw


제가 전달해드리는 내용은 위 영상을 토대로 한 것입니다. 크게 어렵지 않은 내용이고 애니메이션으로 설명을 잘 만든 영상이기 때문에 가능하면 직접 영상을 전부 보시는 것을 권해드립니다. 


보통의 컴퓨터의 메모리는 램같은 휘발성 장치, 혹은 HDD나 SSD 같은 비휘발성 장치에 담겨 있고 CPU 가 통제해서 읽을 수 있는 형태를 띄고 있습니다.


이런 식의 메모리의 특징은 각 정보마다 '위치' 가 존재한다는 중요한 특징이 있습니다. cpu 나 I/O 장치는 어떤 정보가 필요할 때 그 위치로 찾아가면 됩니다.

따라서 정보의 양이 얼마나 되는지, 얼마나 가득찼는지, 비어있는지등을 쉽게 판별할 수가 있으며, 그 정보를 끄집어내는데에 필요한 시간도 상대적으로 일정한 편입니다.


그에 비해 생물의 뇌나 딥러닝 모델이 정보를 기억하는 방식은 전혀 다릅니다.


정보는 일정한 위치에 저장되어 있지 않으며, 한번에 그 정보를 끄집어낼 수도 없습니다. 대신, 일정한 규칙을 토대로 시간 스텝을 밟아가면서 뉴런들간의 연결을 타고 훑어가다보면 원하는 정보를 끄집어낼 가능성이 있는 형태입니다. 이런 형태를 Associative Networks 라고 부릅니다



인간 뇌의 뉴런 그림인데, 가운데 뉴런을 중심으로 주변의 다른 뉴런에 뻗어나가있는 연결들을 볼 수 있습니다.


인공지능 초기부터 학자들은 이것을 수학적으로 특징을 따서 그래프 형태로 모델링할 수 있는 방법을 연구해왔습니다

이와 관련해서는 헵의 규칙이라는 발견이 유명한데 1949년 심리학자인 헵이 '시넵시스 앞과 뒤에서 동시에 신경세포가 흥분할 대 해당 시냅시스의 효율이 강화된다' 라는 논문을 발표했습니다. 이것을 통징적으로 헵의 규칙 또는 헵의 학습규칙이라고 합니다. 그 특징에 주목하여 연결에 가중치를 수치화한 퍼셉트론이라는 모델이 만들어졌고, 퍼셉트론끼리 연결을 어떤 형태로 할까 연구를 거듭하면서 MLP, CNN, RNN, Transformer 같은 다양한 딥러닝 모델이 발전하게 됩니다.


제가 참고한 영상에서 소개한 네트워크는 홉필드 네트워크란 것인데, 뉴런을 서로 연결하고 특정 규칙에 따라 업데이트하면서 상태를 변화시키는 간단한 모델입니다. 여러가지 문제점(아래 글을 보다보면 나옵니다) 때문에 요즘의 모델에서 사용되는 방식은 아니지만 구조가 간단하고, 시각화가 용이해서 이미지의 기억이라는 개념을 설명하기에 적합하기 때문에 이 모델을 선택했습니다. 


위에 보는 것처럼 8*8 픽셀 그리드 형태를 기억하는 홉필드 네트워크를 보면 뉴런이 8*8 형태로 배치되어있고 서로서로 양방향 연결된 형태입니다. 그리고 각 뉴런은 +1 아니면 -1 이라는 모아니면 도 식의 상태값만 가지고 있습니다.  


이 네트워크도 일종의 딥러닝 모델이기 때문에 우리가 원하는 것을 학습을 시킬 수 있고, 그 대상을 각 연결의 가중치라는 형태로 기억하게 됩니다. 


예를 들어서 위 그림의 왼쪽에 있는 숫자 1 모양의 그림을 학습시켰다고 가정해봅시다.

그러면 나중에 네트워크의 초기값을 랜덤으로 준 상태에서 시작해도, 네트워크를 계속 업데이트하다보면 점점 원래의 학습한 형태로 모양이 변합니다.


위의 최종 결과물을 보면 원래 모양과 같은 결과가 나오는 경우도 있고 반전된 결과가 나오는 경우도 있는데 저런 대칭성이 나타나는 것은 홉필드 네트워크의 종특이니까 일단 그러려니 합시다.



이런 네트워크의 기억방식을 잘 비유할 수 있는 대상이 있다면 '메모리폼 베게' 를 예로 들 수 있습니다. 어떤 외부의 주체가 있어서 꾸겨놓았던 베게의 모양을 원래대로 잘 펼쳐주는 것이 아니라, 베게를 구성하는 각 분자들간의 연결구조에 존재하는 연결들의 강함과 약함이 전체 사물의 형태를 기억하는 역할을 하는 것이지요.



그럼 저 네트워크는 저런 그림 한장만 기억할 수 있는 것일까요? 그렇지 않습니다. 저 네트워크는 여러장의 그림을 기억할 수 있습니다.



위의 경우를 보면 4가지 이미지를 학습시켰습니다. 역시 랜덤하게 초기화시켜서 네트워크를 돌리다보면 재미있는 결과가 나오기 시작하는데요




위 그림을 보면 6장의 그림중 4가지는 원래의 학습된 기억을 끄집어냈는데 2가지는 두개의 이미지가 혼합된 결과를 끄집어냅니다. 일종의 할루시네이션이라고 볼 수도 있겠네요.


참고로 저렇게 하나의 네트워크에 여러장의 이미지를 학습시킨 방법은, 각 이미지를 학습한 가중치를 '평균' 을 낸 결과물입니다. 평균을 내서 만든 모델에서 각각 원래의 이미지를 선명하게 학습하는 것이 신기하기도 합니다. 이전 글에서 엠베딩을 설명하면서 mean pooling 이라는 텐서들의 평균을 이용하는 것에 이어서 평균이란 존재가 또 나오네요.


디퓨전에서 체크포인트 모델을 평균을 내서 실사(바질믹스) + 카툰(어비스 오렌지) => 반실사 모델을 만들어내는 신기한 원리의 가장 간단한 사례라고도 할 수 있겠네요. 체크포인트 병합의 경우에도 결국 평균을 내서 만든다는 점에서는 근본적으로 동일합니다.


그럼 이 시점에서 가장 중요한 질문이 남았네요. 저런 모델은 이미지를 몇장이나 기억할 수 있는걸까요? 답은 '모델의 크기와 정확한 패턴의 기억량은 비례한다' 입니다. (홉필드 네트워크의 경우에 한정된 것인지? 다른 종류의 모델에도 통용되는 얘기인지는 확인하지 못했습니다)



'정확한 패턴 (stable memory = 홉필드 네트워크를 돌리면 안정적으로 수렴하는 결과값)' 이라고 한 부분을 주목할 필요가 있습니다. 위의 사례에서 보았듯이 모델은 할루시네이션 같은 부정확한 기억도 만들 수 있습니다. 모델의 규모가 커지고 기억하는 내용들이 많아지다보면, 원래 학습하지는 않았지만 개연성이 있는 조작된 기억이나 기억의 조합들도 만들어낼 수 있는 능력이 생겨납니다. 가끔  꿈을 꾸다보면 내가 겪었던 경험 2가지 이상이 괴이하게 조합되어서 체험하게 되는 경우들이 있는데 이러한 associative memory 의 특성인 것 같ㅅ브니다.


이제 홉필드 네트워크를 통해 네트워크식 기억 방식, 즉 연관식 메모리 (associative memory) 의 느낌을 대강 알았으니 스테이블 디퓨전 (이하 SD)의 모델이라는 실제 사례를 통해서 이미지가 어디에 어떤 형태로 기억되는지 확인해봅시다.


SD 에 대해서 공부를 해보신 분들이라면 SD 는 여러개의 모델이 합쳐서 돌아가는 시스템이란 것을 알고 계실 것입니다. 그 모델들은 각각 CLIP, VAE, 그리고 U-Net 입니다. 이중에서 실제 그림을 그려내는 데에 가장 중요한 역할을 하는 것은 바로 U-Net 입니다. CLIP 은 텍스트 프롬프트와 이미지와의 연관관계에 대한 정보를 담고 있고, VAE 는 저해상도 정보에 해당하는 Latent Space 의 인코딩을 pixel 로 디코딩하는 역할을 합니다. (VAE 에도 이미지를 만들어내는 정보들이 담기긴 했지만 통상적으로 우리가 파인튜닝을 하는 대상은 아니기 때문에 이 글에서 VAE쪽 부분은 논외로 하겠습니다.)


그리고 U-Net 은 그림을 그려내는 리버스 디퓨전 프로세스에서 가장 중요한 역할인 '노이즈 예측' 을 담당합니다


디퓨전 프로세스는 SD 를 학습할 때 사용된다면, 실제 SD 로 그림을 찍어낼 때는 리버스 디퓨전 프로세스를 사용합니다. 흩어져있던 노이즈가 확산의 반대 과정을 거치면서 선명한 이미지로 수렴하게 되는데, 그 비결은 원본 노이즈를 대상을 스케쥴러로 나눠놓은 각 단계에 대해서 U-net 이 대답을 해줄 수 있기 때문입니다


질문        - 지금 보여드리는 이미지는 CFG 에 의거해 추구하는 원본과 비교할때 어떤 노이즈가 낀 걸로 보이나요? 지금의 타임스텝은 t 입니다.

Unet의 답 - 이런 노이즈 이미지가 낀 것으로 예측됩니다 휴먼. [이미지 정보]


그 대답 역시 '어떤 노이즈 패턴 (Predicted noise)' 인데 그 패턴을 원본 이미지에 점점 거둬내게 되면 점점 노이즈가 사라지는 결과물을 얻을 수 있는 것이지요.


이런 '예측된 노이즈' 를 품고 있는 것이 U-net 인데, U-net 이 애니풍 이미지로 학습되었다면 U-Nnet 은 예측된 노이즈를 내놓아야 할 때 애니풍 이미지에 노이즈가 낀 이미지를 기준으로 결과를 내놓겠죠.


U-net 은 원본 사이즈의 이미지를 더 낮은 크기로 점점 줄여서, 결국에는 한줄의 덩어리로 길게 뽑아낸 형태로 변형시키는 CNN 과 그 CNN 을 뒤집은 형태를 서로 연결시킨 모양에 더해서 스킵 연결을 추가한 형태인데요, 

이 경우 생성형 모델에서 이미지를 만드는 데에 가장 큰 역할을 하는 부분은 CNN 을 뒤집어놓은 모양, 즉 작은 크기의 이미지를 더 큰 크기의 이미지로 불리는 업샘플링 역할을 하는 레이어입니다. 이 부분에 관련된 레이어들을 어떻게 적은 수의 파라메터로 뽑아서 커스텀 학습을 시킬까 하는 방법으로 LoRA 가 유명해졌고, 그 후에 여러가지 변종들이 많이 등장하게 됩니다. 자세한 것은 (https://github.com/KohakuBlueleaf/LyCORIS/blob/main/Algo.md) 를 참고하시면 되겠습니다.



언어모델에서도 기억들은 역시 Causal Model 에 가까운 모습으로 저장되는데, 이것은 우리 인간이 정보를 기억하는 것과도 흡사하죠. 집 현관 비밀번호라던가 중요한 전화번호 같은 것들은 그 숫자를 순서대로 기억하는 것은 쉽지만, 거꾸로 기억하는 것은 거의 불가능하다는 것은 스스로 실험해보시면 잘 알 수 있는 사실입니다. 우리의 기억이 순서와 민감한 associative memory 이기 때문에 그렇습니다. 그래서 파이 소숫점 5000 자리까지 기억한다던가 하는 사람들은 순서라는 특징을 최대한 이용할 수 있도록 노래를 만든다던가 어떤 기억을 보조하는 수단들을 동원해서 1자리 부터 '찾아가는' 식으로 기억을 하지, 소숫점 300 자리 숫자는 뭐게? 소숫점 1000 자리 숫자는 뭐게? 하는 질문에는 대답을 못합니다. 제아무리 우영우 할머니가 완벽한 photographic 메모리를 갖고 있더라도 종족이 인간인 이상, 그 기억에 도달하기 위해서는 순서를 밟아나가야 합니다.


언어모델의 내부를 들여다보면, 실제 말들을 찍어내는데 가장 중요한 역할을 하는, 기억에 연관된 부분이라면 트랜스포머의 어텐션쪽보다는 피드포워드 계층이라고 할 수 있습니다. lora 파인튜닝의 경우 QKVO 같은 어텐션 유닛쪽만 대상 모듈로 삼는 경우가 많은데 그러면 새로운 정보나 개념을 학습시키는데에 한계가 있을 수 있습니다. 또한 새로운 개념은 새로운 단어와 연결되어야 하는데 토크나이저를 업데이트 하냐 마냐도 중요한 정보이지요. 예를 들어 크툴루 신화에 대한 정보를 추가하고 싶은데 토크나이저에 '크툴루' 가 없으면 '크' '툴루' 나 '크툴' '루' 혹은 '크', '툴', '루' 같은 식 중의 한가지로 (혹은 아예 바이트 단위로 더 쪼개질 수도 있는) 해석하게 되는데 학습 능력은 떨어질 수 밖에 없겠죠. 

이러한 개념을 잘 활용해서 학습 내용에 따라 적절히 대상 모듈과 하이퍼파라메터, 토크나이저를 수정해야만 좋은 로라 파인튜닝 결과를 얻을 수 있을 것으로 보입니다. 아직까지는 그냥 원클릭으로 쉽게 파인튜닝을 할 수 있어요! 라는 것은 위에서 말한 요소들로 인해 쉽지 않은 부분입니다. 물론 기술이 더 발전하면 자동으로 관련 정보까지 조정해서 파인튜닝을 해주는 방법이 나올 수도 있을 것입니다.


하지만 굳이 파인튜닝이 아니라 정보들을 적당한 문장단위 청크로 나누고 각각의 엠베딩을 따놓아서 벡터디비에 인덱싱 한 다음에 필요할 때마다 찾아와서 프롬프트에 덧붙여주는 방식 - RAG = Retrieval Augmented Generation 이 있기 때문에 이쪽이 더 효율성은 높을 것입니다. AI 채팅의 경우 월드인포나 로어북 같은것을 요 방식으로 구현하면 좋겠지요.



이상으로 딥러닝 모델의 기억에 대한 정보와 관련 상식들을 간단히 알아보았습니다. 언제나 그렇지만 추가로 궁금하신점, 정정이 필요한 부분은 댓글로 남겨주세요.


읽어주셔서 감사합니다.