# Positional Bias Experiment

이 실험은 GLEE 모델에서 텍스트 임베딩의 위치적 편향(positional bias)을 분석하기 위한 것입니다. 프롬프트 앞에 공백을 추가하여 단어의 위치를 변경하고, 모델이 위치에 얼마나 의존하는지 확인합니다.

## 실험 목적

1. **위치적 편향 확인**: 모델이 단어의 위치에 얼마나 민감한지 분석
2. **임베딩 안정성 평가**: 위치 변화에 따른 임베딩 변화량 측정
3. **모델 강건성 분석**: 다양한 위치 변화에 대한 모델의 반응 패턴 파악

## 실험 원리

### 기본 아이디어
- `prompts[batch_size:]`부터 positive, negative가 혼재된 참조 프롬프트들이 위치
- 이 프롬프트들 앞에 공백을 추가하여 단어의 위치를 변경
- 의미는 동일하지만 위치가 다른 프롬프트들의 임베딩을 비교

### 실험 구조

#### 고정 길이 모드
```
Original: "positive person"
Modified: "     positive person"  # 5 spaces added
```

#### 랜덤 길이 모드
```
Original: "positive person"
Modified: "   positive person"    # 3 spaces (random)
Modified: "        positive person"  # 8 spaces (random)
Modified: "  positive person"     # 2 spaces (random)
```

### 예상 결과
- **높은 코사인 유사도 (>0.9)**: 위치적 편향이 적음
- **낮은 코사인 유사도 (<0.7)**: 위치적 편향이 큼
- **높은 위치적 분산**: 위치 변화가 임베딩에 큰 영향을 미침

## 파일 구조

```
glee/
├── models/
│   └── glee_model.py                    # 수정된 모델 (위치적 편향 실험 기능 추가)
├── utils/
│   └── positional_bias_analyzer.py      # 실험 결과 분석 도구
├── configs/
│   └── positional_bias_experiment.yaml  # 실험 설정 파일
├── run_positional_bias_experiment.py    # 실험 실행 스크립트
└── README_positional_bias_experiment.md # 이 파일
```

## 사용법

### 1. 고정 길이 실험

#### 단일 실험
```bash
python run_positional_bias_experiment.py \
    --config path/to/your/config.yaml \
    --single-experiment 5 \
    --output-dir ./results
```

#### 비교 실험
```bash
python run_positional_bias_experiment.py \
    --config path/to/your/config.yaml \
    --space-lengths 1 5 10 15 20 \
    --output-dir ./results
```

### 2. 랜덤 길이 실험

#### 단일 랜덤 실험
```bash
python run_positional_bias_experiment.py \
    --config path/to/your/config.yaml \
    --random-experiments "1:10" \
    --random-only \
    --output-dir ./results
```

#### 여러 랜덤 실험 비교
```bash
python run_positional_bias_experiment.py \
    --config path/to/your/config.yaml \
    --random-experiments "1:5" "5:15" "10:25" \
    --random-only \
    --output-dir ./results
```

#### 고정 길이와 랜덤 길이 혼합 실험
```bash
python run_positional_bias_experiment.py \
    --config path/to/your/config.yaml \
    --space-lengths 1 5 10 \
    --random-experiments "1:10" "5:20" \
    --output-dir ./results
```

### 3. 설정 파일을 통한 실험 활성화

#### 고정 길이 모드
```yaml
# config.yaml
MODEL:
  POSITIONAL_BIAS_EXPERIMENT: True
  SPACE_PREFIX_LENGTH: 5
  RANDOM_SPACE_LENGTH: False
```

#### 랜덤 길이 모드
```yaml
# config.yaml
MODEL:
  POSITIONAL_BIAS_EXPERIMENT: True
  RANDOM_SPACE_LENGTH: True
  MIN_SPACE_LENGTH: 1
  MAX_SPACE_LENGTH: 20
```

## 실험 결과

### 출력 파일들

1. **similarity_analysis.png**: 코사인 유사도, L2 거리, 크기 변화 분석
2. **positional_analysis.png**: 위치적 분산 분석
3. **experiment_report.txt**: 상세한 실험 보고서
4. **results.json**: 구조화된 실험 결과
5. **experiment_comparison.png**: 여러 실험 간 비교 (비교 실험 시)

### 결과 해석

#### 코사인 유사도 분석
- **0.95-1.00**: 매우 강한 유사도 (위치적 편향 없음)
- **0.85-0.95**: 강한 유사도 (약간의 위치적 편향)
- **0.70-0.85**: 중간 유사도 (중간 정도의 위치적 편향)
- **<0.70**: 약한 유사도 (큰 위치적 편향)

#### L2 거리 분석
- **<0.1**: 매우 작은 변화
- **0.1-0.3**: 작은 변화
- **0.3-0.5**: 중간 변화
- **>0.5**: 큰 변화

#### 위치적 분산 분석
- **낮은 분산**: 위치 변화에 강건함
- **높은 분산**: 위치 변화에 민감함

## 코드 수정 사항

### 1. `get_text_embedding` 함수 수정

```python
def get_text_embedding(self, prompts, teacher=False, plus=False, 
                      positional_bias_experiment=False, space_prefix_length=5,
                      random_space_length=False, min_space_length=1, max_space_length=20):
    if positional_bias_experiment and len(prompts) > 0:
        # Split prompts into original and experimental parts
        batch_size = len(prompts) // 7
        original_prompts = prompts[:batch_size]
        experimental_prompts = prompts[batch_size:]
        
        # Generate space prefixes
        if random_space_length:
            import random
            space_lengths = [random.randint(min_space_length, max_space_length) for _ in experimental_prompts]
            experimental_prompts_with_spaces = []
            for i, prompt in enumerate(experimental_prompts):
                space_prefix = " " * space_lengths[i]
                experimental_prompts_with_spaces.append(space_prefix + prompt)
        else:
            # Use fixed space length
            space_prefix = " " * space_prefix_length
            experimental_prompts_with_spaces = [space_prefix + prompt for prompt in experimental_prompts]
```

### 2. 설정 기반 제어

```python
positional_bias_enabled = getattr(self.cfg.MODEL, 'POSITIONAL_BIAS_EXPERIMENT', False)
space_prefix_length = getattr(self.cfg.MODEL, 'SPACE_PREFIX_LENGTH', 5)
random_space_length = getattr(self.cfg.MODEL, 'RANDOM_SPACE_LENGTH', False)
min_space_length = getattr(self.cfg.MODEL, 'MIN_SPACE_LENGTH', 1)
max_space_length = getattr(self.cfg.MODEL, 'MAX_SPACE_LENGTH', 20)
```

## 실험 예시

### 입력 프롬프트
```
grounding_prompts = ["person", "car"]
reference_prompts = [
    "positive person", "negative person", "positive car", "negative car",
    "positive person", "negative person", "positive car", "negative car"
]
```

### 고정 길이 모드 결과
```
grounding_prompts = ["person", "car"]
reference_prompts = [
    "     positive person", "     negative person", "     positive car", "     negative car",
    "     positive person", "     negative person", "     positive car", "     negative car"
]
```

### 랜덤 길이 모드 결과
```
grounding_prompts = ["person", "car"]
reference_prompts = [
    "   positive person", "        negative person", "  positive car", "     negative car",
    "      positive person", "   negative person", "        positive car", "  negative car"
]
```

### 분석 결과 예시
```
=== Positional Bias Experiment Report ===
Space Prefix Length: random_1_20

SIMILARITY ANALYSIS:
- Mean Cosine Similarity: 0.9234
- Mean L2 Distance: 0.1567
- Mean Magnitude Change: 0.0234

POSITIONAL ANALYSIS:
- Mean Positional Variance: 0.0456
- Std Positional Variance: 0.0123

INTERPRETATION:
- High cosine similarity (0.9234) suggests minimal positional bias
- Low positional variance (0.0456) suggests embeddings are robust to positional changes
```

## 고급 분석

### 1. 토크나이저 분석
실험에서는 토크나이저가 공백을 어떻게 처리하는지도 분석합니다:
- 원본 토큰 길이 vs 수정된 토큰 길이
- 토큰 시프트량 계산

### 2. 배치별 분석
6개씩 그룹화된 참조 프롬프트들의 위치적 변화를 배치별로 분석합니다.

### 3. 비교 실험
다양한 공백 길이에 대한 실험을 비교하여 최적의 설정을 찾습니다.

### 4. 랜덤 vs 고정 길이 비교
랜덤 길이와 고정 길이 실험을 비교하여 더 효과적인 방법을 찾습니다.

## 주의사항

1. **메모리 사용량**: 실험 중 추가적인 임베딩 계산으로 인한 메모리 사용량 증가
2. **계산 시간**: 토크나이저 분석 및 시각화로 인한 추가 시간
3. **결과 해석**: 높은 유사도가 항상 좋은 것은 아님 (과적합 가능성)
4. **랜덤성**: 랜덤 길이 실험은 매번 다른 결과를 생성할 수 있음

## 확장 가능성

1. **다양한 위치 변화**: 공백 외에 다른 문자나 토큰 추가
2. **다양한 모델**: 다른 텍스트 인코더와의 비교
3. **실제 성능 영향**: 위치적 편향이 실제 태스크 성능에 미치는 영향 분석
4. **분포 기반 분석**: 랜덤 길이의 분포 패턴 분석

## 문제 해결

### 일반적인 오류들

1. **CUDA 메모리 부족**: 배치 크기 줄이기
2. **토크나이저 오류**: 프롬프트 길이 제한 확인
3. **설정 파일 오류**: YAML 문법 확인
4. **랜덤 실험 오류**: 최소/최대 길이 범위 확인

### 디버깅 팁

1. 로그 출력 확인: `[Positional Bias Experiment]` 태그가 있는 메시지들
2. 토큰 길이 비교: 원본 vs 수정된 토큰 길이 차이
3. 임베딩 형태 확인: 텐서 차원 및 디바이스 확인
4. 랜덤 길이 확인: 실제 사용된 공백 길이들 로그 확인 