[.NET]Using Transformers Models : Extending TransformersSharp

최근 프로젝트에서 텍스트/이미지 임베딩을 .NET 환경에서 직접 활용할 방법을 찾아보다가, TransformersSharp라는 프로젝트를 발견했다. 이 라이브러리는 Hugging Face의 transformers Python 라이브러리를 C#에서 직접 호출할 수 있도록 wrapping한 형태다. 덕분에 별도의 Python 서버를 띄우고 REST API를 붙이지 않아도 .NET 코드 안에서 곧바로 모델을 다룰 수 있다.

TransformersSharp는 기본적으로 텍스트 기반 임베딩과 파이프라인 기능들을 제공한다. 예를 들어 SentenceTransformer를 통해 문장을 벡터화할 수 있지만 이미지를 벡터화 할 수는 없다.

그래서 직접 TransformersSharp를 fork(Link)해서 기능을 다음과 같이 확장했다.

Python Wrapper

sentence_transformers_wrapper.py에 다음 함수를 추가했다.

def load_image(url_or_path):
    if url_or_path.startswith("http://") or url_or_path.startswith("https://"):
        return Image.open(requests.get(url_or_path, stream=True).raw)
    else:
        return Image.open(url_or_path)

def encode_image(model: SentenceTransformer, image_path: str) -> Buffer:
    """
    Encode an image using the SentenceTransformer model.
    """
    image = load_image(image_path)
    return model.encode(image)

C# Wrapper

SentenceTransformer.cs에는 다음 메서드를 추가했다.

public float[] GenerateImage(string image_path)
{
    var result = TransformerEnvironment.SentenceTransformersWrapper
        .EncodeImage(transformerObject, image_path);
    return result.AsFloatReadOnlySpan().ToArray();
}

이제 텍스트와 이미지를 같은 환경에서 임베딩할 수 있다.

using Microsoft.Extensions.AI;
using TransformersSharp;

var transformer_text = SentenceTransformer.FromModel(
    "sentence-transformers/clip-ViT-B-32-multilingual-v1", 
    trustRemoteCode: true);

var transformer_image = SentenceTransformer.FromModel(
    "clip-ViT-B-32", 
    trustRemoteCode: true);

var text_embeddings = transformer_text.GenerateSentence("A dog in the snow");
var image_embeddings = transformer_image.GenerateImage(
    "https://images.unsplash.com/photo-1547494912-c69d3ad40e7f?...");

Console.WriteLine($"Text Vector: {string.Join(", ", text_embeddings.Take(10))}...");
Console.WriteLine($"Image Vector: {string.Join(", ", image_embeddings.Take(10))}...");

Python 서버 없이도 .NET 안에서 바로 모델을 다룰 수 있다는 점이 굉장히 편리한 부분이 있었다. TransformersSharp 자체는 아직 완성도가 높은 수준은 아니지만, 필요한 기능을 확장할 수 있어서 오히려 테스트 해보기 좋았다.

[LLM] What is layer normalization?

딥러닝 모델을 학습할 때, 정규화(Normalization)는 빠르고 안정적인 학습을 위한 핵심 기법 중 하나다. 특히 자연어 처리(NLP)에서 사용되는 트랜스포머 기반 LLM(Large Language Model)에서는 층 정규화(Layer Normalization)가 중요한 역할을 한다.

정규화는 딥러닝 모델에서 입력 데이터가 일정한 분포(평균과 분산)를 갖도록 조정해주는 기법이다. 정규화를 통해 모델은 다음과 같은 이점을 얻을 수 있다

  • 학습이 더 안정적이고 빠르게 진행 됨.
  • 과적합(Overfitting)방지에 도움 됨.
  • DNN(Deep neural network) architecture에서도 정보 흐름이 원활 함.

Batch Normalization VS Layer Normalization

Batch Normalization

배치 정규화는 입력 데이터를 배치 단위로 묶어서 평균과 분산을 계산하고 정규화한다. 주로 이미지 처리 분야에서 사용되며, 자연어 처리에서는 아래 이미지 처럼 문장마다 길이가 다르더라도 일정한 길이로 맞추기 위해 PAD 토큰이 삽입된다.

배치 마다 구성데이터가 달라서 정규화 효과가 일정하지 않게 되서 LLM에서는 일반적으로 Bath Norm을 사용하지 않는다.

Layer Normalization

층 정규화는 각 샘플(토큰 임베딩)마다 독립적으로 정규화한다. 같은 문장 안의 각 단어 벡터를 기준으로 평균과 분산을 계산한다.

토큰 임베딩별 정규화를 수행하기 때문에 문장의 길이에 영향을 받지 않고 정규화를 동일하게 적용할 수 있다.

LLM과 같은 트랜스포머 기반 자연어 처리 모델에서는, 입력의 다양성과 길이의 불균형을 고려해 배치 정규화 대신 층 정규화를 사용한다. 이는 모델이 더 빠르고 안정적으로 학습될 수 있도록 돕고, 문맥 이해 능력을 향상시키는 중요한 기법이다.