Whisper에서 발생하는 환각(hallucination) 문제 해결

Whisper에서 발생하는 환각(hallucination) 문제는 음성을 잘못 인식하거나 문맥에 맞지 않는 텍스트를 생성하는 현상입니다. 이를 해결하기 위해 다음 방법을 시도할 수 있습니다.

  1. Silero VAD 설정 조정:
  • Whisper와 Silero VAD를 함께 사용할 때, VAD의 임계값을 조정하여 음성 감지가 더 정확하게 이루어지도록 할 수 있습니다. 예를 들어, 감지 민감도를 높이거나 낮추어 Whisper가 필요하지 않은 부분을 인식하지 않도록 조정할 수 있습니다.
  • VAD의 설정값인 0 또는 1을 시도해보는 것도 좋습니다. 이 값이 음성 감지의 민감도를 조정하며, 필요할 때 로그 확률을 사용하여 자동으로 temperature를 조정할 수 있습니다. 낮은 temperature 설정은 모델의 출력을 더 안정적으로 만들 수 있습니다.
  1. Temperature 조정:
  • Whisper 모델의 temperature 파라미터를 낮게 설정하면 모델의 출력이 더 결정적(deterministic)이 되어 환각을 줄일 수 있습니다. 너무 낮추면 다양성은 감소하지만, 과도한 환각 문제를 줄일 수 있습니다.
  1. 로그 확률 사용:
  • Whisper가 생성하는 텍스트의 로그 확률을 검토하여 특정 임계값 이하의 확률을 가진 단어는 환각으로 처리하고 제거하는 방식으로 해결할 수 있습니다.
  1. 후처리 단계 적용:
  • Whisper가 출력하는 텍스트에 대한 후처리를 통해 의심스러운 단어 또는 문장을 필터링하는 알고리즘을 추가하면, 환각을 줄이는 데 도움이 됩니다.
  1. 모델 업데이트:
  • Whisper 모델의 최신 버전이나 개선된 음성 인식 모델을 사용하여 환각 문제를 줄일 수 있습니다. 최신 버전은 더 나은 성능과 환각 문제 해결에 도움을 줄 수 있습니다.

이러한 접근 방법들을 함께 사용하면 Whisper에서 발생하는 환각 문제를 효과적으로 줄일 수 있습니다.

Silero (씨레로)

Silero는 음성 관련 모델과 솔루션을 제공하는 소프트웨어로, 음성 활동 감지(VAD), 텍스트를 자연스러운 음성으로 변환하는 텍스트-투-스피치(TTS) 등의 기능을 제공합니다. 특히 Silero VAD는 음성 인식에서 음성 활동을 감지하여, 실제로 말하고 있는 구간만을 처리하는 데 사용됩니다. Silero의 주요 장점은 GPU나 복잡한 학습 과정이 필요 없으며, 간단하게 설치하여 사용할 수 있다는 것입니다.

Silero VAD는 음성 활동 감지(Voice Activity Detection)를 위한 알고리즘으로, 음성 샘플에 대해 0에서 1 사이의 값을 반환합니다. 이 값은 해당 샘플이 음성을 포함하고 있을 확률을 나타내며, 특정 임계값을 기준으로 음성 구간을 판별합니다.

Silero는 영어 발음으로 “씨-레-로” (silero)라고 읽습니다.

Silero는 음성 감지의 최소화된 모델로, 여러 언어에서 자연스러운 발음을 지원하며, GPU가 필요하지 않아서 저사양 환경에서도 사용할 수 있는 것이 특징입니다.

CUDA 프로그래밍: GPU를 활용한 컴퓨팅의 세계

개요

CUDA는 엔비디아가 자체 GPU에서의 일반 컴퓨팅을 위해 개발한 병렬 컴퓨팅 플랫폼이자 프로그래밍 모델입니다. CUDA를 통해 개발자는 연산의 병렬화가 가능한 부분에 GPU의 성능을 활용하여 컴퓨팅 집약적인 애플리케이션의 속도를 높일 수 있습니다.

CUDA 프로그래밍의 핵심 개념

CUDA 프로그래밍을 이해하기 위해서는 몇 가지 핵심 개념을 파악해야 합니다:

1. 커널 (Kernels)

  • 커널은 GPU (장치)에서 실행되는 함수입니다.
  • 여러 스레드에서 병렬적으로 실행되도록 설계되었습니다.

2. 스레드 계층 구조 (Thread Hierarchy)

  • CUDA에서 스레드가 어떻게 구성되는지 나타냅니다.
  • 스레드는 블록으로 그룹화되고, 블록은 그리드로 그룹화됩니다.

3. 메모리 계층 구조 (Memory Hierarchy)

  • CUDA는 글로벌 메모리, 공유 메모리, 상수 메모리를 포함한 복잡한 메모리 계층 구조를 가지고 있습니다.
  • 각 메모리 유형은 액세스 방법에 영향을 미치는 다른 속성을 가지고 있습니다.

4. 이기종 프로그래밍 (Heterogeneous Programming)

  • CUDA를 통해 CPU와 GPU 모두에서 실행되는 프로그램을 작성할 수 있습니다.
  • 이는 계산 집약적인 부분과 메모리 집약적인 부분으로 작업을 분할할 수 있는 작업에 유용합니다.

5. 비동기 SIMT 프로그래밍 모델 (Asynchronous SIMT Programming Model)

  • 단일 명령, 다중 스레드 (SIMT) 프로그래밍 모델은 CUDA의 기본 개념입니다.
  • 즉, 단일 명령이 여러 스레드에 의해 동시에 실행될 수 있습니다.
  • 비동기 프로그래밍을 통해 커널 실행을 호스트와 장치 간 데이터 전송과 같은 다른 작업과 중첩할 수 있습니다.

6. 계산 능력 (Compute Capability)

  • GPU의 계산 능력은 세대와 기능을 나타냅니다.
  • CUDA 프로그램을 작성할 때 GPU의 계산 능력을 고려하는 것이 중요합니다. 이는 일부 기능이 이전 GPU에서는 지원되지 않을 수 있기 때문입니다.

7. 성능 최적화 전략 (Performance Optimization Strategies)

  • CUDA 프로그램의 성능을 최적화하는 방법에는 여러 가지가 있습니다.
  • 여기에는 활용도 극대화, 메모리 처리량 극대화, 명령 처리량 극대화 등이 포함됩니다.

CUDA 프로그래밍의 간단한 예시: 행렬 곱셈

CUDA 프로그래밍의 핵심 개념을 이해하기 위해 간단한 예시를 살펴보겠습니다. 이 예시에서는 두 개의 행렬을 곱하는 작업을 GPU에서 수행합니다.

1. 코드 구조

C++
#include <iostream>

__global__ void matrixMul(float *A, float *B, float *C, int N) {
  int row = blockIdx.y * blockDim.y + threadIdx.y;
  int col = blockIdx.x * blockDim.x + threadIdx.x;

  if (row < N && col < N) {
    float sum = 0.0f;
    for (int k = 0; k < N; k++) {
      sum += A[row * N + k] * B[k * N + col];
    }
    C[row * N + col] = sum;
  }
}

int main() {
  int N = 1024; // 행렬의 크기

  // 행렬 A와 B를 CPU에서 생성 및 초기화
  float *A, *B, *C;
  A = (float *)malloc(N * N * sizeof(float));
  B = (float *)malloc(N * N * sizeof(float));
  C = (float *)malloc(N * N * sizeof(float));

  // 행렬 A와 B를 GPU 메모리로 전송
  float *dA, *dB, *dC;
  cudaMalloc((void **)&dA, N * N * sizeof(float));
  cudaMalloc((void **)&dB, N * N * sizeof(float));
  cudaMalloc((void **)&dC, N * N * sizeof(float));

  cudaMemcpy(dA, A, N * N * sizeof(float), cudaMemcpyHostToDevice);
  cudaMemcpy(dB, B, N * N * sizeof(float), cudaMemcpyHostToDevice);

  // 커널 실행 (GPU에서 행렬 곱셈 수행)
  matrixMul<<<(N / blockDim.x, N / blockDim.y), blockDim>>>(dA, dB, dC, N);

  // 결과를 GPU 메모리에서 CPU로 전송
  cudaMemcpy(C, dC, N * N * sizeof(float), cudaMemcpyDeviceToHost);

  // 결과 행렬 C 출력
  for (int i = 0; i < N; i++) {
    for (int j = 0; j < N; j++) {
      std::cout << C[i * N + j] << " ";
    }
    std::cout << std::endl;
  }

  // GPU 메모리 해제
  free(A);
  free(B);
  free(C);
  cudaFree(dA);
  cudaFree(dB);
  cudaFree(dC);

  return 0;
}

2. 코드 설명

2.1. __global__ 키워드

  • __global__ 키워드는 해당 함수가 GPU에서 실행되는 커널임을 나타냅니다.

2.2. matrixMul 커널 함수

  • matrixMul 함수는 두 개의 입력 행렬 (A와 B)와 출력 행렬 (C)을 받습니다.
  • blockIdxthreadIdx는 각 블록과 스레드의 인덱스를 제공합니다.
  • blockDim은 각 블록의 크기를 나타냅니다.
  • 코드는 각 스레드가 행렬의 한 요소를 계산하도록 구성됩니다.

2.3. main 함수

  • main 함수는 CPU에서 행렬을 생성하고 초기화합니다.
  • GPU 메모리에 공간을 할당하고 행렬을 GPU 메모리로 전송합니다.
  • matrixMul 커널을 실행하여 행렬 곱셈을 수행합니다.
  • 결과를 GPU 메모리에서 CPU로 전송하고 출력합니다.
  • 마지막으로 GPU 메모리를 해제합니다.

추가 정보

위의 예시는 CUDA 프로그래밍의 기본적인 개념을 보여주는 간단한 예시입니다. 실제 CUDA 프로그래밍은 더 복잡할 수 있으며, 더 많은 기능과 최적화 기술을 포함할 수 있습니다.

양자화로 소수점 아래를 제거하는 예

양자화는 모델의 가중치나 활성화 함수 등을 표현하는 데이터의 비트 수를 줄여서 모델의 크기를 축소하고 연산량을 감소시키는 기술입니다. 소수점 아래의 비트를 제거하는 것은 이러한 양자화의 한 형태입니다.
특히, 딥러닝 모델을 배포할 때 제한된 메모리 및 계산 능력을 가진 장치에서 효과적으로 사용될 수 있습니다.

즉 쉽게 이해하시면 되는게 소수점 아래를 제거하는 것입니다.

양자화를 통해 소수점 아래를 제거하는 예를 보여드리겠습니다. 아래의 예제는 Python과 PyTorch를 사용하여 간단한 숫자를 양자화하는 방법을 보여줍니다.

코드 콜랩에서 돌리기

import torch

# 원본 숫자
original_number = 3.14159265358979323846

# 원본 숫자를 torch.float32로 변환
float32_number = torch.tensor(original_number, dtype=torch.float32)

# 원본 숫자를 torch.float16로 변환하여 소수점 아래를 제거
float16_number = torch.tensor(original_number, dtype=torch.float16)

# 결과 출력
print(“Original number:”, original_number)
print(“Float32 number:”, float32_number)
print(“Float16 number:”, float16_number)
“`

결과:
“`
Original number: 3.141592653589793
Float32 number: tensor(3.1416)
Float16 number: tensor(3.1406, dtype=torch.float16)
“`

위의 예제에서 볼 수 있듯이, 원본 숫자인 3.141592653589793의 경우, torch.float32로 변환하면 3.1416으로, torch.float16으로 변환하면 3.1406으로 나타납니다. 이것은 torch.float16이 소수점 아래를 제거하여 더 낮은 정밀도를 제공하기 때문입니다.

AI 용어 – 최소한의 파라미터로 사전 훈련된 모델 – LoRA(저랭크 적응, Low-Rank Adaptation)

LoRA(저랭크 적응, Low-Rank Adaptation)는 대규모 언어 모델의 파라미터 수를 크게 줄이면서도 모델의 성능을 유지하는 방법입니다. 일반적으로 대규모 모델을 훈련시킬 때, 전체 모델을 다시 훈련시키는데는 막대한 비용과 시간이 소요됩니다. LoRA는 이러한 문제를 해결하기 위한 방법으로 개발되었습니다.

일반적으로, 예를 들어 GPT-3 175B와 같이 거대한 언어 모델을 사용할 때, 모델을 특정 작업이나 도메인에 맞게 재조정하려면 독립된 모델을 새로 훈련해야 합니다. LoRA는 이런 부담을 줄이기 위해 개발되었습니다.

LoRA의 아이디어는 기존의 사전 훈련된 모델 가중치를 동결하고, 각 레이어의 파라미터 수를 크게 줄이면서도 모델의 유용성을 유지하는 것입니다. 이를 위해 각 레이어에 훈련 가능한 랭크 분해 행렬을 주입합니다. 이 방식은 모델의 훈련 가능한 파라미터 수를 크게 줄여주는 동시에 메모리 요구량을 줄여줍니다.

결과적으로 LoRA를 적용하면, 파라미터 수를 크게 줄일 수 있으면서도 모델의 품질이 크게 하락하지 않는다는 것입니다. 이는 효율적으로 훈련 가능한 파라미터 수를 줄여 비용을 절감하면서도 모델의 성능을 유지할 수 있는 방법을 제시합니다.

논문.

“Low-Rank Adaptation of Large Language Models” (LoRA)에 대한 논문 요약입니다. 이 논문은 자연어 처리의 중요한 패러다임 중 하나인 일반 도메인 데이터의 대규모 사전 훈련과 특정 작업 또는 도메인에 대한 적응을 다룹니다.

논문에서는 대규모 모델을 사전 훈련할수록 모든 모델 파라미터를 다시 훈련하는 “full fine-tuning”이 점차 더 어려워진다는 문제점을 지적합니다. 예를 들어 GPT-3 175B를 사용한다면, 각각이 175B의 파라미터를 가진 독립적인 fine-tuned 모델을 배포하는 것이 매우 비용이 많이 든다고 합니다.

LoRA는 이러한 문제를 해결하기 위해 제안되었는데, 사전 훈련된 모델 가중치를 유지하고 Transformer 아키텍처의 각 레이어에 학습 가능한 랭크 분해 행렬을 삽입하여 하위 작업의 학습 가능한 파라미터 수를 크게 줄입니다. LoRA는 Adam으로 fine-tuning 된 GPT-3 175B와 비교하여 학습 가능한 파라미터 수를 10,000배 줄이고 GPU 메모리 요구량을 3배로 줄일 수 있다고 합니다.

LoRA는 RoBERTa, DeBERTa, GPT-2 및 GPT-3의 모델 품질에서 fine-tuning과 유사하거나 더 우수한 성능을 보이며, 학습량이 더 높고 어댑터와 달리 추가적인 추론 지연이 없습니다. 이를 통해 언어 모델 적응에서 랭크 결핍에 대한 실험 결과를 제공하여 LoRA의 효과를 밝히고 있습니다.

이 논문은 PyTorch 모델과 LoRA를 통합하는 데 도움을 주는 패키지를 제공하고 있으며, RoBERTa, DeBERTa 및 GPT-2의 구현과 모델 체크포인트를 이용할 수 있도록 URL을 제공합니다. 이 논문은 Computation and Language (cs.CL); Artificial Intelligence (cs.AI); Machine Learning (cs.LG) 분야의 arXiv:2106.09685에 출판되었습니다.

더 많은 정보를 원한다면, 해당 링크인 https://doi.org/10.48550/arXiv.2106.09685를 참조할 수 있습니다.

 

활성화 함수(Activation Function)

활성화 함수(Activation Function)는 인공 신경망의 각 뉴런에서 입력 신호의 가중합을 출력값으로 변환하는 함수를 말합니다. 이 함수는 인공 신경망의 비선형성을 추가하고, 신경망이 복잡한 함수를 근사하고 다양한 패턴을 학습할 수 있도록 합니다.

활성화 함수는 다음과 같은 역할을 합니다:

1. 비선형성 추가: 활성화 함수는 입력과 가중치의 선형 결합을 비선형 함수로 변환합니다. 이것은 신경망이 복잡한 함수를 모델링하고 다양한 종류의 데이터 패턴을 파악할 수 있게 합니다. 선형 함수만으로는 다층 신경망이 복잡한 문제를 풀 수 없습니다.

2. 신경망의 출력 생성: 활성화 함수는 출력층의 뉴런에서 최종 예측 값을 생성합니다. 예를 들어, 분류 문제의 경우 확률값을 출력하기 위해 시그모이드 활성화 함수가 사용될 수 있고, 회귀 문제의 경우 선형 활성화 함수가 사용될 수 있습니다.

일반적으로 사용되는 활성화 함수에는 다음과 같은 것들이 있습니다:

– 시그모이드(Sigmoid) 함수: 주로 이진 분류 문제의 출력층에 사용됩니다.
– 하이퍼볼릭 탄젠트(Tanh) 함수: 신경망의 은닉층에서 사용되며, 입력값을 -1과 1 사이로 압축합니다.
– 렐루(ReLU, Rectified Linear Unit) 함수: 은닉층에서 많이 사용되며, 입력이 양수일 때 선형적인 활성화를 수행하고 음수일 때 0으로 변환합니다.
– 리키 렐루(Leaky ReLU) 함수: ReLU의 변형으로, 음수 값에 작은 기울기를 부여하여 “죽은 뉴런” 문제를 완화시킵니다.
– GELU(Gaussian Error Linear Unit) 함수: 뉴런의 출력을 훈련하는 데 더 용이하게 만드는 새로운 활성화 함수입니다.

각 활성화 함수는 특정 문제나 아키텍처에 따라 적합한 역할을 수행합니다.

어텐션 모델의 위치 임베딩(Positional Embedding)

어텐션 모델의 위치 임베딩(Positional Embedding)은 문장이나 시퀀스 내에서 단어의 위치 정보를 벡터로 표현하는 기법입니다. 어텐션 메커니즘은 주로 단어 간의 상대적인 위치 정보를 활용하여 중요한 단어에 집중하고 관련 정보를 파악하는 데 사용됩니다. 하지만 어텐션 모델은 단어들을 순서대로 처리하며 위치 정보를 명시적으로 제공하지 않기 때문에 위치 임베딩을 따로 사용하여 이를 보완합니다.

일반적으로 위치 임베딩은 삼각 함수(주로 사인과 코사인 함수)를 활용하여 단어의 위치를 벡터로 인코딩합니다. 이 함수들은 서로 다른 파장과 주기를 가지며, 각 위치에 대한 고유한 패턴을 생성합니다. 이렇게 생성된 위치 임베딩을 단어의 임베딩과 더하여 최종 입력으로 활용합니다. 위치 임베딩은 어텐션 메커니즘이 단어의 상대적 위치를 이해하고 문맥을 파악하는 데 도움을 줄 수 있습니다.

유사도 내적 계산

유사도 내적 계산은 벡터 간의 유사도를 측정하는 한 가지 방법입니다. 벡터는 숫자들의 배열로 이루어진 개념으로, 예를 들면 [1, 2, 3]과 같이 나타낼 수 있습니다. 벡터 간의 유사도는 두 벡터가 얼마나 비슷한지를 나타내는 척도로 사용됩니다.

유사도 내적 계산은 두 벡터의 대응하는 요소들을 각각 곱한 뒤 그 결과들을 모두 더하여 유사도 값을 구합니다. 이러한 연산을 요소별 곱(또는 Hadamard 곱)과 합으로 표현할 수 있습니다.

두 벡터 A와 B의 유사도 내적 계산은 다음과 같습니다:

유사도 내적 값 = Σ(A[i] * B[i]) for i = 0 to N-1

여기서 N은 벡터의 차원을 의미하며, A[i]와 B[i]는 각 벡터의 i번째 요소를 나타냅니다.

유사도 내적 계산은 머신러닝, 자연어 처리 등 다양한 분야에서 중요한 개념으로 활용됩니다. 예를 들어, 어텐션 메커니즘에서는 쿼리와 키 간의 유사도 내적을 사용하여 중요한 정보를 찾고, 벡터 간의 유사도 내적 값을 비교하여 유사성을 평가하는데 활용됩니다.

구글 바드(BARD)와 ChatGPT의 근본적인 차이점 – 구글 바드는 도구를 활용한다.

구글 BARD와 ChatGPT의 근본적인 차이점은 다음과 같습니다:

1. 모델 기반:

ChatGPT는 오픈AI에서 개발한 GPT 시리즈의 언어 모델로, 트랜스포머(Transformer) 논문에서 제안된 아키텍처에 기반을 두고 있습니다. 트랜스포머는 시퀀스 투 시퀀스(Sequence-to-Sequence) 모델을 개선한 구조로, 주로 자연어 처리 작업에서 뛰어난 성능을 보입니다.

반면에 BARD는 구글이 발표한 LaMDA(Language Models for Dialog Applications) 논문에 기반을 두고 있습니다. LaMDA는 대화형 언어 모델에 대한 연구로, ChatGPT와는 다른 모델 아키텍처와 접근 방식을 가지고 있습니다. 따라서 BARD와 ChatGPT는 각각 다른 기반과 특징을 가진 언어 모델입니다.

 

2. 도구를 활용하는 바드: BARD는 효율적인 사실 확인과 숫자 계산을 위해 툴셋(Tool Set, TS)을 사용합니다. LaMDA-Base 모델은 예비 답변을 생성하는 역할을 하고, LaMDA-Research 모델은 인터넷 검색, 번역 및 계산 도구와 협력하여 정확한 답변을 생성합니다.

아래 그림은 람다 논문에 나온 툴셋활용 예시 그림입니다.

“에펠탑은 언제 지어졌니?”라는 유저 질문에 답을 하는 LaMDA 작동 예시입니다.

3. 답변 검증: LaMDA-Research 모델은 이전에 생성된 답변을 검증하고 외부 툴셋이 필요한 경우 해당 도구에 질문과 답변을 제출합니다. 이를 통해 BARD는 더 정확한 답변을 제공할 수 있습니다. ChatGPT는 이와 달리 내부적으로 사실 확인 및 검증을 수행하지 않습니다.

요약하면, BARD는 LaMDA 논문을 기반으로 하며, 툴셋을 활용하여 사실 확인과 숫자 계산의 효율성을 높입니다. 이에 반해 ChatGPT는트랜스포머 모델을 기반으로 하며, 사실 확인과 숫자 계산에 제한이 있을 수 있습니다.

언어모델의 완전 이해 강의 !

트랜스포머 모델로 GPT만들기

 

트랜스포머 모델의 일반적인 과정: 1 전처리, 2아키텍처 구성, 3예측 및 학습, 4후처리, 5 평가 및 추론

트랜스포머 모델의 일반적인 과정은 다음과 같습니다:

1. 데이터 전처리: 입력 데이터를 모델이 처리할 수 있는 형태로 변환합니다. 이 단계에는 텍스트 데이터의 토큰화, 임베딩, 패딩 등이 포함될 수 있습니다. 전처리는 모델에 입력되는 데이터의 형식을 맞추고, 필요한 정보를 추출하거나 변환하는 역할을 합니다.

2. 모델 아키텍처 구성: 트랜스포머 모델의 아키텍처를 구성합니다. 이는 입력 데이터와 출력 데이터의 차원, 임베딩 크기, 레이어의 개수, 어텐션 메커니즘의 유형 등을 정의하는 단계입니다. 트랜스포머 모델은 인코더와 디코더로 구성되며, 각각은 여러 개의 트랜스포머 블록으로 이루어져 있습니다.

3. 예측 및 학습: 전처리된 데이터를 모델에 입력하여 예측과 학습을 수행합니다. 모델은 입력 시퀀스의 다음 단어를 예측하거나 원하는 작업을 수행합니다. 예측과 학습 단계에서는 트랜스포머 모델의 다양한 레이어와 메커니즘이 활용되며, 학습 데이터를 통해 모델의 가중치가 업데이트됩니다.

4. 후처리: 모델의 출력을 원하는 형태로 변환하거나 활용하는 단계입니다. 이는 디코딩, 인덱싱 연산, 다항분포 샘플링 등을 포함할 수 있으며, 모델의 출력을 자연어로 표현하거나 다른 작업에 활용할 수 있도록 합니다.

5. 평가 및 추론: 훈련된 모델을 사용하여 평가나 추론을 수행합니다. 평가는 모델의 성능을 측정하고 개선하는 과정을 의미하며, 추론은 새로운 입력에 대해 모델이 예측을 수행하는 과정을 의미합니다.

트랜스포머 모델의 일반적인 과정은 위와 같이 전처리, 아키텍처 구성, 예측 및 학습, 후처리, 평가 및 추론으로 이루어집니다. 이러한 과정을 반복하면서 모델을 훈련하고 개선하여 원하는 작업에 대해 좋은 성능을 발휘할 수 있도록 합니다.