티스토리 뷰
면접이 아주 처참하게 망했다.
따라서 이 글은 면접에서 나왔던 질문들에 대한 셀프 피드백 되시겠다.
질문이 굉장히 많았고, 긴장해서 머리가 하얗게 되서 제대로 답변 못한 문제가 많다.
내 입장에서도 정말 제대로 된 문제들이라고 생각해서 제대로 적어놓기로 했다.
내가 면접 본 곳이 어딘지는 밝히지 않으니 보안 문제는 되지 않으리라 믿는다.
Q. Okt, Kiwi, kkma 토크나이저의 작동 차이점은?
그 중에서도 Okt가 가지는 특징은 무엇인가?
A. Okt는 한국어 텍스트를 분리하고 품사 태깅을 수행한다.
트위터와 같은 짧은 텍스트에서 잘 작동하도록 설계되었다.
자주 사용되는 단어(명사, 형용사, 동사)를 잘 인식하지만 복잡한 문장 구조에서는 부정확할 수 있다.
Kiwi 토크나이저는 사용자 정의 규칙을 추가할 수 있고, 병렬 처리로 인해 빠르다.
형태소 분리와 함께 어근 추출도 제공한다.
Kkma 토크나이저는 문장 분리와 구문 분석을 지원한다. 학습된 데이터에 기반하여 정확도가 높지만 다른 Okt나 Kiwi 토크나이저에 비해 느리다.
소셜 텍스트 처럼 비정형 데이터에는 Okt가 유리하고, 아니라면 다른 토크나이저가 유리할 수 있다.
Q. 객체 지향 프로그래밍이 무엇인가?
A. 객체 지향 프로그래밍은 프로그램을 여러 개의 독립된 객체로 나누어 설계하는 프로그램 패러다임이다.
코드의 재사용성, 확장성, 유지보수성을 높이기 위해 설계되었다.
객체 : 현실 세계의 개념을 반영하여 프로그램으로 구현된 독립 객체
데이터(속성)과 동작(메서드)를 포함한다.
상속 : 기존 클래스의 속성과 메서드를 자식 클래스가 사용할 수 있는 것
코드의 재사용성과 계층 관계를 형성하는 역할을 한다.
캡슐화(은닉화) : 속성과 메서드를 하나로 묶고, 외부로부터 내부 함수의 구현을 숨긴다.
추상화 : 복잡한 시스템에서 필요한 부분만 추출해서 간단하게 표현하는 개념.
Q. SOLID 원칙 중 하나만 설명하세요.
이건 gpt의 답변으로 대신하겠다.
**SOLID 원칙**은 객체 지향 프로그래밍에서 설계의 유연성과 유지보수성을 높이기 위해 사용되는 다섯 가지 원칙의 집합입니다. 이 원칙들은 소프트웨어 설계의 품질을 향상시키고, 코드의 재사용성과 확장성을 높이는 데 도움을 줍니다. 각 원칙은 Robert C. Martin(“Uncle Bob”)에 의해 정의되었으며, 아래와 같이 다섯 가지 원칙으로 구성됩니다.
### 1. 단일 책임 원칙 (Single Responsibility Principle, SRP)
- **원칙**: 클래스는 하나의 책임만 가져야 하며, 하나의 클래스는 단 하나의 기능만을 담당해야 합니다.
- **설명**: 클래스가 여러 가지 기능을 수행하면 변경 사항이 발생할 때 그 영향이 복잡해질 수 있습니다. 단일 책임 원칙을 따름으로써 클래스를 변경하는 이유가 하나로 제한되어 유지보수가 용이해집니다.
- **예시**: 사용자 정보를 저장하고, 데이터를 출력하는 두 가지 기능을 하나의 클래스에서 처리하지 않고, 사용자 정보 저장 클래스와 출력 클래스를 별도로 만들어 각각의 책임을 분리합니다.
### 2. 개방-폐쇄 원칙 (Open/Closed Principle, OCP)
- **원칙**: 소프트웨어 요소는 확장에는 열려 있어야 하지만, 수정에는 닫혀 있어야 합니다.
- **설명**: 새로운 기능을 추가할 때 기존의 코드를 수정하지 않고도 확장할 수 있어야 합니다. 이 원칙을 지키기 위해 인터페이스와 추상화를 적극적으로 활용합니다.
- **예시**: 새로운 결제 방식(카드, 페이팔 등)을 추가할 때 기존 코드에 직접적인 변경을 가하지 않고, 추상화된 결제 인터페이스를 구현하는 방식으로 추가할 수 있습니다.
### 3. 리스코프 치환 원칙 (Liskov Substitution Principle, LSP)
- **원칙**: 자식 클래스는 언제나 부모 클래스를 대체할 수 있어야 합니다.
- **설명**: 상속받은 자식 클래스는 부모 클래스의 기능을 그대로 수행할 수 있어야 하며, 이를 위반하지 않아야 합니다. 즉, 자식 클래스가 부모 클래스와 같은 인터페이스를 통해 상호작용할 때 예상된 동작을 수행해야 합니다.
- **예시**: 예를 들어, 직사각형(Rectangle) 클래스의 자식으로 정사각형(Square) 클래스를 상속할 때, 정사각형이 직사각형의 속성(너비와 높이)을 그대로 사용하지 못하면 LSP를 위반하게 됩니다.
### 4. 인터페이스 분리 원칙 (Interface Segregation Principle, ISP)
- **원칙**: 특정 클라이언트를 위한 인터페이스 여러 개가 범용 인터페이스 하나보다 낫습니다.
- **설명**: 클라이언트가 자신이 사용하지 않는 메서드에 의존하지 않아야 하며, 불필요한 의존성을 줄이기 위해 역할에 맞는 작은 인터페이스들을 사용해야 합니다.
- **예시**: 프린터 인터페이스를 만들 때, `Print`, `Scan`, `Fax` 기능을 가진 큰 인터페이스 대신, 각 기능에 맞는 인터페이스를 별도로 만들어 필요한 기능만 구현하도록 합니다.
### 5. 의존 역전 원칙 (Dependency Inversion Principle, DIP)
- **원칙**: 고수준 모듈은 저수준 모듈에 의존해서는 안 되며, 둘 다 추상화에 의존해야 합니다. 추상화는 구체적인 사항에 의존해서는 안 되며, 구체적인 사항이 추상화에 의존해야 합니다.
- **설명**: 모듈 간의 의존성을 줄이기 위해, 저수준 모듈(구체적인 구현부)이 아닌, 추상화된 인터페이스나 추상 클래스에 의존하도록 설계해야 합니다.
- **예시**: 데이터베이스 연결을 구현할 때, 구체적인 데이터베이스 클래스(MySQLConnector 등)에 의존하지 않고, `DatabaseConnector` 인터페이스에 의존하도록 설계합니다.
이 다섯 가지 원칙은 소프트웨어 설계의 품질을 높이고, 유지보수성과 확장성을 확보하기 위한 기본 원칙으로 널리 사용되고 있습니다. SOLID 원칙을 따르면 코드가 보다 이해하기 쉽고, 수정과 확장이 용이해져, 장기적으로 소프트웨어 개발 비용을 줄이는 데 기여할 수 있습니다.
Q. BM25는 어떻게 작동하는가? 그리고 사용자가 조정할 수 있는 하이퍼파라미터는 검색에 어떤 영향을 주는가?
BM25는 문서와 질의 간의 관련성을 평가하여 검색 결과의 순위를 매기는 확률적 정보 검색 모델이다.
작동 방식은 각 용어의 빈도(TF)와 역문서 빈도(IDF)를 결합하여 질의에 포함된 각 용어가 문서에서 얼마나 중요한지를 계산하는 것이다. 용어 빈도는 비선형 함수로 조정되어 용어의 출현 빈도가 증가할수록 가중치가 감소한다. 또한, 문서 길이에 따라 점수를 보정하여 긴 문서가 과도하게 높은 점수를 받지 않도록 한다.
사용자가 조정할 수 있는 주요 하이퍼파라미터는 \(k_1\)과 \(b\)이다. \(k_1\)은 용어 빈도의 영향을 조정하며, 값이 클수록 용어 빈도가 랭킹에 더 큰 영향을 준다. \(b\)는 문서 길이의 영향을 조정하며, 0에 가까울수록 길이 보정이 적고, 1에 가까울수록 길이에 민감하게 반응한다. 이러한 하이퍼파라미터 조정은 검색 결과의 정밀도와 재현율에 직접적인 영향을 준다.
Q. 프로세스와 스레드에 대해서 설명하세요.
프로세스는 운영체제에서 실행 중인 프로그램의 단위이다. 프로세스는 독립적인 메모리 공간을 가지고, 각각의 프로세스는 코드, 데이터, 힙, 스택 영역으로 나뉜다. 프로세스 간에는 메모리 공간이 분리되어 있어 다른 프로세스의 메모리에 직접 접근할 수 없으며, 이를 통해 프로세스 간의 안전성을 유지할 수 있다.
스레드는 프로세스 내에서 실행되는 작업의 단위이다. 스레드는 프로세스의 자원을 공유하며, 같은 메모리 공간에서 실행된다. 하나의 프로세스는 여러 스레드를 가질 수 있으며, 스레드들은 프로세스의 힙과 데이터 영역을 공유하지만, 각각 독립적인 스택을 가진다. 스레드의 공유 특성 덕분에 스레드 간 통신이 빠르고 효율적이지만, 자원 공유로 인한 동기화 문제를 해결해야 한다.
프로세스는 서로 독립적이지만, 스레드는 프로세스의 자원을 공유하며 동작하는 단위이다.
Q. relu가 무엇이며, 왜 relu를 많이 쓰는가?
기존의 시그모이드를 사용할 때, 역전파 메커니즘에서 가중치를 업데이트 하는 방법은 해당하는 활성화 함수를 각 층마다 미분하며 맨 끝의 레이어부터 초기 레이어까지 곱해주는 형태이다.
그러나 레이어가 깊어지면 깊어질수록 시그모이드는 연속으로 미분했을 때 미분 값이 0에 수렴하고, 그렇게 되면 초기 레이어는 거의 업데이트가 되지 않는 Vanishing Gradient 문제가 발생한다. 이로 인해서 활성화 함수를 비선형인 relu로 바꾸면, 아예 미분 값을 0 또는 1로 고정할 수 있고, 그렇게 역전파 메커니즘을 완성할 수 있기에 relu를 사용한다.
Q. Transformer 구조는 무엇인가?
Transformer는 Self-Attention을 기반으로 한 Encoder-Decoder 형태의 아키텍처이다. Self-Attention은 단어와 단어 사이의 유사도를 dot product로 계산하고, 이를 n*n의 행렬로 만들어 그 중에서 가장 높은 형태의 점수를 가진 단어와 단어를 매칭하여 결과로 내놓는다.
그런 Self-Attention 구조만으로 Encoder-Decoder로 만들어낸 것이 Transformer이다. Query와 Key는 위에서 봤던 것처럼 Self-Attention 구조의 행렬을 만드는 것이고, 거기서 이제 가중치의 형태를 가지는 게 Value 값이다.
Q. KcElectra의 원리는 무엇인가?
KcElectra는 한국어 자연어 처리를 위한 사전학습된 언어 모델로, 구글의 Electra 모델을 한국어에 최적화한 버전이다. Electra의 원리를 기반으로 하며, 일반적인 마스크드 언어 모델(Masked Language Model)과는 다른 차별화된 학습 방식을 사용한다.
Electra는 텍스트의 일부 토큰을 마스킹하고 이를 예측하는 대신, 텍스트 내 일부 토큰을 교체(replace)하는 방식으로 학습된다. Electra는 생성기(Generator)와 판별기(Discriminator)로 구성되며, 생성기는 입력 텍스트에서 일부 토큰을 예측하고 교체한다. 판별기는 생성기가 교체한 토큰이 원본인지, 교체된 것인지를 판별하는 역할을 한다. 판별기의 목표는 생성기의 예측을 구분하는 것이며, 이 과정에서 보다 효과적으로 텍스트의 언어적 특징을 학습할 수 있다.
KcElectra는 이 원리를 따르면서도 한국어 특성에 맞춘 데이터로 학습된 모델이다. KcElectra는 특히 한국어 소셜 미디어, 뉴스, 일상 대화 데이터 등으로 학습하여, 한국어의 구어체와 다양한 문맥에서의 자연어 처리 능력을 향상시킨다. 이를 통해 KcElectra는 한국어 처리에서 보다 높은 성능을 보이며, 감정 분석, 질의응답, 문서 분류 등 다양한 한국어 NLP 태스크에서 우수한 성능을 발휘한다.
Electra의 Replace & Detect 방식은 보다 효율적인 학습과 고속 처리가 가능하게 하며, KcElectra는 이를 통해 한국어 데이터에 특화된 강력한 자연어 처리 모델로 작동한다.
Q. Text augmentation의 종류와 방법?
Back Translation이 진짜 갑자기 생각이 안나서 아예 답변을 못했다..진짜 억울했던 질문.
Text augmentation은 자연어 처리(NLP) 모델의 성능을 향상시키기 위해 텍스트 데이터를 다양하게 변형하고 증강하는 방법이다. 데이터의 다양성을 높여 모델의 일반화 성능을 향상시키고, 데이터의 불균형을 완화하는 데 도움이 된다. 주요 텍스트 증강 기법은 다음과 같다.
### 1. **역번역(Back Translation)**
- **방법**: 원본 문장을 다른 언어로 번역한 후 다시 원본 언어로 재번역하여 새로운 문장을 생성하는 방법이다.
- **예시**: "I love coffee"를 "나는 커피를 좋아한다"로 번역한 후, 다시 영어로 번역하여 "I like coffee"와 같은 변형된 문장을 얻는다.
### 2. **동의어 교체(Synonym Replacement)**
- **방법**: 문장에서 몇몇 단어를 동의어로 교체하여 문장을 변형한다.
- **예시**: "The quick brown fox"에서 "quick"을 "fast"로 바꾸어 "The fast brown fox"로 만든다.
### 3. **랜덤 삽입(Random Insertion)**
- **방법**: 문장에 동의어나 관련된 단어를 무작위 위치에 삽입한다.
- **예시**: "The cat sits"에 "quietly"를 추가하여 "The quietly cat sits"로 변형한다.
### 4. **랜덤 삭제(Random Deletion)**
- **방법**: 문장에서 단어를 무작위로 삭제하여 데이터를 증강한다.
- **예시**: "The cat sits on the mat"에서 "on"을 삭제하여 "The cat sits the mat"로 만든다.
### 5. **랜덤 교환(Random Swap)**
- **방법**: 문장 내의 단어들의 위치를 무작위로 교환하여 문장을 변형한다.
- **예시**: "The cat sits on the mat"에서 "sits"와 "cat"의 위치를 바꾸어 "Sits the cat on the mat"로 만든다.
### 6. **노이즈 추가(Adding Noise)**
- **방법**: 문장에 철자 오류, 구두점 변경 등 작은 노이즈를 추가하여 모델이 다양한 오류를 다루도록 학습한다.
- **예시**: "The cat sits"를 "The catt sits"로 철자 오류를 추가한다.
### 7. **텍스트 혼합(Mixup)**
- **방법**: 두 개의 문장을 혼합하여 새로운 문장을 생성하는 기법이다.
- **예시**: "The cat sits"와 "A dog barks"를 혼합하여 "The cat barks"와 같은 새로운 문장을 만든다.
### 8. **문장 재배열(Sentence Shuffling)**
- **방법**: 문단에서 문장의 순서를 바꾸어 새로운 문장을 생성한다.
- **예시**: 문단 내 문장의 순서를 무작위로 재배열한다.
### 9. **Paraphrasing (의역)**
- **방법**: 원래 문장을 유사한 의미의 다른 문장으로 변환하는 기법이다.
- **예시**: "He is very fast"를 "He runs quickly"로 바꾼다.
이러한 증강 기법들은 NLP 모델의 데이터 다양성을 높이고, 모델이 다양한 표현과 오류에 견고하게 학습될 수 있도록 돕는다.
Q. 가상환경이란 무엇이고, 어떻게 만드는가?
**가상환경(Virtual Environment)**은 Python에서 특정 프로젝트에 필요한 라이브러리와 패키지를 독립적으로 관리할 수 있는 격리된 작업 공간이다. 가상환경을 사용하면 프로젝트마다 서로 다른 라이브러리 버전을 사용할 수 있어, 프로젝트 간의 종속성 충돌을 방지할 수 있다. 이를 통해 개발자는 특정 프로젝트의 요구사항에 맞게 패키지를 설치하고 관리할 수 있으며, 시스템 전체의 Python 환경에 영향을 주지 않는다.
### 가상환경 만드는 방법
가상환경은 Python에서 제공하는 `venv` 모듈이나 `virtualenv` 패키지를 사용하여 만들 수 있다.
1. **Python의 `venv` 모듈 사용하기:**
- Python 3.3 버전 이상에서는 `venv` 모듈을 기본 제공한다.
- 가상환경을 생성하려면, 터미널 또는 명령 프롬프트에서 다음 명령어를 실행한다.
```bash
python -m venv 가상환경_이름
```
- 예를 들어, `myenv`라는 이름의 가상환경을 생성하려면:
```bash
python -m venv myenv
```
2. **가상환경 활성화하기:**
- 가상환경을 활성화하려면, OS에 따라 다음 명령어를 사용한다.
- **Windows**:
```bash
myenv\Scripts\activate
```
- **macOS/Linux**:
```bash
source myenv/bin/activate
```
- 활성화되면 명령줄에 가상환경 이름이 표시되며, 이후 설치되는 패키지는 이 가상환경에만 영향을 미친다.
3. **가상환경 비활성화하기:**
- 가상환경을 비활성화하려면 다음 명령어를 사용한다.
```bash
deactivate
```
4. **`virtualenv` 패키지 사용하기:**
- Python 2.x나 더 많은 기능을 필요로 할 경우 `virtualenv`를 사용한다.
- `virtualenv` 설치:
```bash
pip install virtualenv
```
- 가상환경 생성:
```bash
virtualenv 가상환경_이름
```
- 이후 활성화 및 비활성화 과정은 `venv`와 동일하다.
가상환경을 사용하면 프로젝트별로 독립된 Python 환경을 유지할 수 있어, 각 프로젝트의 종속성과 패키지 버전을 효과적으로 관리할 수 있다.