├── .DS_Store ├── README.md ├── common ├── arg.py └── dataset.py ├── data ├── sample.txt ├── train │ └── kowiki_sample.txt └── vocab-v1.txt ├── images ├── explicit-sparse-attention.png ├── macaron.png ├── residual_attn.png └── rezero.png ├── model ├── o_transformer.py ├── pipeline.py └── transformer.py ├── requirements.txt ├── train ├── config.json └── run_pretraining.py ├── train_deepspeed ├── __pycache__ │ └── ds_util.cpython-36.pyc ├── config_rezero_sparsetopk.json ├── ds_config_rezero_sparsetopk.json ├── ds_train_rezero_sparsetopk.sh ├── ds_util.py └── train_rezero_sparsetopk.py └── train_pl ├── config.json ├── config_small.json ├── run_pretraining.py ├── run_pretraining_rezero.py └── run_pretraining_rezero_sparsetopk.py /.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nawnoes/pytorch-gpt-x/6d6d8b3ef3c66a5f454e4a722fdbc26268312b89/.DS_Store -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # GPT-X 2 | Implementation of autoregressive language model(like GPT) using improved Transformer and DeepSpeed pipeline parallelism. 3 | 4 | ## Improved Transformer 5 | Transformer used in this repository attempts to improve the transformer using the additional modules below. 6 | | Name | Description | Link | 7 | |-----------------------------|--------------------------------------------------------------------------------------------|------------------------------------------------| 8 | | Rezero | Rezero Is All You Need | [link](https://arxiv.org/abs/2003.04887) | 9 | | Explicit Sparse Transformer | Concentrated Attention Through Explicit Selection | [link]( https://arxiv.org/abs/1912.11637 ) | 10 | | Macaron Architecture | Understanding and Improving Transformer From a Multi-Particle Dynamic System Point of View | [link]( https://arxiv.org/pdf/1906.02762.pdf ) | 11 | | RealFormer | Residual Attention | [link]( https://arxiv.org/abs/2012.11747 ) | 12 | | ALiBi Position Embedding | effective relative positional encoding | | 13 | 14 | ## Model Description 15 | | model_name | n_params | n_layer | d_model | n_heads | vocab_size | max_seq_len | learning_rate | 16 | |:----------:|----------|---------|---------|---------|------------|-------------|---------------| 17 | | GPT-X 1B | 1B | 20 | 2048 | 16 | 22000 | 1024 | 2.0 x 10^-4 | 18 | 19 | ## DeepSpeed 20 | DeepSpeed is a deep learning training optimization library, providing the means to train massive billion parameter models at scale. 21 | 22 | ### Piepline Parallelism 23 | You can train 1B GPT-X Model using deepspeed pipeline parallelism on 2 V100 GPU(16G). 24 | 25 | #### GPU Usage 26 | ``` 27 | +-----------------------------------------------------------------------------+ 28 | | NVIDIA-SMI 418.39 Driver Version: 418.39 CUDA Version: 10.1 | 29 | |-------------------------------+----------------------+----------------------+ 30 | | GPU Name Persistence-M| Bus-Id Disp.A | Volatile Uncorr. ECC | 31 | | Fan Temp Perf Pwr:Usage/Cap| Memory-Usage | GPU-Util Compute M. | 32 | |===============================+======================+======================| 33 | | 0 Tesla V100-PCIE... On | 00000000:00:06.0 Off | 0 | 34 | | N/A 42C P0 44W / 250W | 16076MiB / 16130MiB | 99% Default | 35 | +-------------------------------+----------------------+----------------------+ 36 | | 1 Tesla V100-PCIE... On | 00000000:00:07.0 Off | 0 | 37 | | N/A 45C P0 168W / 250W | 16060MiB / 16130MiB | 99% Default | 38 | +-------------------------------+----------------------+----------------------+ 39 | 40 | +-----------------------------------------------------------------------------+ 41 | | Processes: GPU Memory | 42 | | GPU PID Type Process name Usage | 43 | |=============================================================================| 44 | | 0 29525 C /home/ubuntu/anaconda3/bin/python 16065MiB | 45 | | 1 29528 C /home/ubuntu/anaconda3/bin/python 16049MiB | 46 | +-----------------------------------------------------------------------------+ 47 | ``` 48 | #### Pipeline Parallelism Log 49 | ``` 50 | [2021-12-31 12:24:20,042] [INFO] [engine.py:93:__init__] CONFIG: micro_batches=4 micro_batch_size=1 51 | [2021-12-31 12:24:20,094] [INFO] [engine.py:151:__init__] RANK=1 STAGE=1 LAYERS=12 [11, 23) STAGE_PARAMS=548560916 (548.561M) TOTAL_PARAMS=1099214888 (1099.215M) UNIQUE_PARAMS=1099214888 (1099.215M) 52 | [2021-12-31 12:24:20,094] [INFO] [engine.py:151:__init__] RANK=0 STAGE=0 LAYERS=11 [0, 11) STAGE_PARAMS=550653972 (550.654M) TOTAL_PARAMS=1099214888 (1099.215M) UNIQUE_PARAMS=1099214888 (1099.215M) 53 | ``` 54 | 55 | ``` 56 | [2021-12-31 12:24:08,793] [INFO] [module.py:365:_partition_layers] Partitioning pipeline stages with method parameters 57 | stage=0 layers=11 58 | 0: Embedding 59 | 1: ReZeroSparseTopkDecoder 60 | 2: ReZeroSparseTopkDecoder 61 | 3: ReZeroSparseTopkDecoder 62 | 4: ReZeroSparseTopkDecoder 63 | 5: ReZeroSparseTopkDecoder 64 | 6: ReZeroSparseTopkDecoder 65 | 7: ReZeroSparseTopkDecoder 66 | 8: ReZeroSparseTopkDecoder 67 | 9: ReZeroSparseTopkDecoder 68 | 10: ReZeroSparseTopkDecoder 69 | stage=1 layers=12 70 | 11: ReZeroSparseTopkDecoder 71 | 12: ReZeroSparseTopkDecoder 72 | 13: ReZeroSparseTopkDecoder 73 | 14: ReZeroSparseTopkDecoder 74 | 15: ReZeroSparseTopkDecoder 75 | 16: ReZeroSparseTopkDecoder 76 | 17: ReZeroSparseTopkDecoder 77 | 18: ReZeroSparseTopkDecoder 78 | 19: ReZeroSparseTopkDecoder 79 | 20: ReZeroSparseTopkDecoder 80 | 21: LayerNorm 81 | 22: Linear 82 | loss: cross_entropy 83 | ``` 84 | 85 | 86 | ## TODO 87 | 88 | - [x] ~~ReZero~~ 89 | - [x] ~~RealFormer, Residual Attention~~ 90 | - [x] ~~Macaron architectures~~ 91 | - [x] ~~Macaron architectures - layer Scale 0.5~~ 92 | - [x] ~~Explicit Sparse Transformer~~ 93 | - [x] ~~torch lightning~~ 94 | - [x] ~~Deepspeed train on single GPU~~ 95 | - [x] apply wandb 96 | - [x] Deepspeed pipeline parallel trainig on 2 V100 GPU with 16GB Memory 97 | 98 | ## Parameter For Few-shot 99 | GPT-3 has a 175B parameter, and the size of the model is important for few-shot learning. In this repository, I try to pretrain language model as large as possible using 2 V100 GPUs. 100 | 101 | ## GPT-3 Config 102 | | model_name | n_params | n_layer | d_model | n_heads | d_head | batch_size | learning_rate | 103 | |:----------:|----------|---------|---------|---------|--------|------------|---------------| 104 | | GPT-3 175B | 175B | 96 | 12288 | 96 | 128 | 3.2M | 0.6 x 10^-4 | 105 | | GPT-3 13B | 13B | 40 | 5140 | 40 | 128 | 2M | 1.0 x 10^-4 | 106 | | GPT-3 6.7B | 6.7B | 32 | 4096 | 32 | 128 | 2M | 1.2 x 10^-4 | 107 | | GPT-3 2.7B | 2.7B | 32 | 2560 | 32 | 80 | 1M | 1.6 x 10^-4 | 108 | | GPT-3 1.3B | 1.3B | 24 | 2048 | 24 | 128 | 1M | 2.0 x 10^-4 | 109 | 110 | ## Issue 111 | - `AttributeError: module 'deepspeed' has no attribute 'zero'`: reinstall deepspeed 112 | - `userwarning: cuda initialization: the nvidia driver on your system is too old`: reinstall pytorch following by cuda version 113 | **my solution**-GPU V100, cuda 10.1 114 | 115 | ```sh 116 | pip install torch==1.7.1+cu101 torchvision==0.8.2+cu101 torchaudio==0.7.2 -f https://download.pytorch.org/whl/torch_stable.html 117 | ``` 118 | - `can't find CUDA_HOME path`: reinstall cuda 119 | # References 120 | **Transformer** 121 | 122 | - [lucidrains/x-transformers](https://github.com/lucidrains/x-transformers) 123 | 124 | **DeepSpeed** 125 | 126 | - [DeepSpeed](https://www.deepspeed.ai/) 127 | - [DeepSpeed Core API Doc](https://deepspeed.readthedocs.io/en/latest/index.html) 128 | 129 | **ReZero** 130 | 131 | - [/majumderb/rezero](https://github.com/majumderb/rezero/blob/master/rezero/transformer/rztx.py) 132 | 133 | **Explicit Sparse Transformer** 134 | 135 | - [x-transformer: explicit_sparse_transformer](https://github.com/lucidrains/x-transformers/blob/2badf9261cda03e1497b5db62274b045cd827086/x_transformers/x_transformers.py#L469) 136 | 137 | **Macaron Architecrue** 138 | 139 | - [Understanding and Improving Transformer From a Multi-Particle Dynamic System Point of View](https://arxiv.org/pdf/1906.02762.pdf) 140 | 141 | **RealFormer Residual Attention** 142 | - [cloneofsimo/RealFormer-pytorch](https://github.com/cloneofsimo/RealFormer-pytorch/blob/main/models.py) 143 | 144 | **DeepSpeed** 145 | - [PyTorch lightning DeepSpeed](https://pytorch-lightning.readthedocs.io/en/stable/advanced/advanced_gpu.html#deepspeed) 146 | 147 | **Pipeline Parallelism** 148 | - [DeepSpeed Pipeline Parallelism](https://www.deepspeed.ai/tutorials/pipeline/) 149 | - [DeepSpeedExamples](https://github.com/microsoft/DeepSpeedExamples/tree/1fed12e8b375b0c54902827e7140d8266dfccd59/pipeline_parallelism) 150 | - [EleutherAI/gpt-neox](https://github.com/EleutherAI/gpt-neox/blob/49e60fe7ad14f6991a7fa678d3a0c330d09b9ff4/megatron/training.py) -------------------------------------------------------------------------------- /common/arg.py: -------------------------------------------------------------------------------- 1 | import json 2 | 3 | class Arg: 4 | def __init__(self, **entries): 5 | self.__dict__.update(entries) 6 | 7 | class ModelConfig: 8 | def __init__(self, config_path): 9 | self.config_path = config_path 10 | f = open(self.config_path, 'r') 11 | self.config_json = json.load(f) 12 | self.arg = Arg(**self.config_json) 13 | 14 | def get_config(self): 15 | return self.arg 16 | 17 | if __name__=='__main__': 18 | configs = ModelConfig('/ds_config.json').get_config() 19 | print(configs) 20 | 21 | 22 | -------------------------------------------------------------------------------- /common/dataset.py: -------------------------------------------------------------------------------- 1 | import warnings 2 | warnings.filterwarnings("ignore") 3 | 4 | import os 5 | import logging 6 | import torch 7 | from tqdm import tqdm 8 | from torch.utils.data import Dataset 9 | from common.arg import ModelConfig 10 | from transformers import BertTokenizer 11 | 12 | class GPTXDataset(Dataset): 13 | def __init__(self, tokenizer, max_len, dir_path): 14 | logging.info('Start pretraining data load!') 15 | 16 | self.tokenizer = tokenizer 17 | self.max_len =max_len 18 | self.docs = [] 19 | 20 | # 파일 리스트 21 | file_list = os.listdir(dir_path) 22 | 23 | # num_lines = sum(1 for line in open(path, 'r',encoding='utf-8')) 24 | file_progress_bar = tqdm(file_list, position=0, leave=True, bar_format='{l_bar}{bar:10}{r_bar}') 25 | for file_name in file_progress_bar: 26 | path = f'{dir_path}/{file_name}' 27 | data_file = open(path, 'r',encoding='utf-8') 28 | for line in tqdm(data_file, 29 | desc='Data load for pretraining', 30 | position=1, leave=True): 31 | line = line[:-1] 32 | self.docs.append(line) 33 | logging.info('Complete data load') 34 | 35 | def _tokenize_input_ids(self, input_ids: list, add_special_tokens:bool = False, pad_to_max_length: bool = True): 36 | inputs = torch.tensor(self.tokenizer.encode(input_ids, add_special_tokens=add_special_tokens, max_length=self.max_len, pad_to_max_length=pad_to_max_length, return_tensors='pt',truncation=True)) 37 | return inputs 38 | def __len__(self): 39 | return len(self.docs) 40 | 41 | def __getitem__(self, idx): 42 | inputs = self._tokenize_input_ids(self.docs[idx], pad_to_max_length=True) 43 | labels = inputs.clone() 44 | 45 | inputs= inputs.squeeze() 46 | labels= labels.squeeze() 47 | 48 | 49 | return inputs, labels 50 | 51 | class GPTXDatasetV2(Dataset): 52 | def __init__(self, tokenizer, max_len, dir_path): 53 | logging.info('Start pretraining data load!') 54 | 55 | self.tokenizer = tokenizer 56 | self.max_len =max_len 57 | self.docs = [] 58 | 59 | # 파일 리스트 60 | file_list = os.listdir(dir_path) 61 | 62 | # num_lines = sum(1 for line in open(path, 'r',encoding='utf-8')) 63 | file_progress_bar = tqdm(file_list, position=0, leave=True, bar_format='{l_bar}{bar:10}{r_bar}') 64 | for file_name in file_progress_bar: 65 | path = f'{dir_path}/{file_name}' 66 | data_file = open(path, 'r',encoding='utf-8') 67 | 68 | tmp_line = [self.tokenizer.cls_token_id] 69 | for line in tqdm(data_file, 70 | desc='Data load for pretraining', 71 | position=1, leave=True): 72 | line = line[:-1] 73 | line_ids = self.tokenizer.encode(line, add_special_tokens=False, pad_to_max_length=False, 74 | max_length=max_len - 2, truncation=True) 75 | line_ids += [self.tokenizer.sep_token_id] 76 | 77 | if len(tmp_line) + len(line_ids) < self.max_len: 78 | tmp_line += line_ids 79 | else: 80 | self.docs.append(tmp_line) 81 | tmp_line = [self.tokenizer.cls_token_id] 82 | 83 | logging.info('Complete data load') 84 | 85 | def _tokenize_input_ids(self, input_ids: list, add_special_tokens:bool = False, pad_to_max_length: bool = True): 86 | inputs = torch.tensor(self.tokenizer.encode(input_ids, add_special_tokens=add_special_tokens, max_length=self.max_len, pad_to_max_length=pad_to_max_length, return_tensors='pt',truncation=True)) 87 | return inputs 88 | def __len__(self): 89 | return len(self.docs) 90 | 91 | def __getitem__(self, idx): 92 | inputs = self._tokenize_input_ids(self.docs[idx], pad_to_max_length=True) 93 | labels = inputs.clone() 94 | 95 | inputs= inputs.squeeze() 96 | labels= labels.squeeze() 97 | 98 | 99 | return inputs, labels 100 | 101 | if __name__=='__main__': 102 | data_path = '../data/sample.txt' 103 | config_path = '../train_pl/config.json' 104 | config = ModelConfig(config_path=config_path).get_config() 105 | 106 | # Tokenizer 107 | tokenizer = BertTokenizer(vocab_file='../data/vocab-v1.txt', do_lower_case=False) 108 | dataset = GPTXDataset(tokenizer, config.max_seq_len, '../data/train/') 109 | print(dataset) 110 | -------------------------------------------------------------------------------- /data/sample.txt: -------------------------------------------------------------------------------- 1 | 대류열 전달 2 | 대류열 전달(Convective heat transfer)은 간단히 대류라고도 하며 이류를 통해 한 장소에서 다른 장소로 열을 전달시키는 것을 말한다. 3 | 열이 물체를 통해서 이동하는 것이 아니라 따뜻해진 유체(액체나 기체)의 흐름에 의해서 고온 부분에서 저온 부분으로 이동하는 현상을 열의 대류라고 한다. 4 | 열전도와는 달라서 대류는 열이 운동하는 유체를 따라서 이동한다. 5 | 이런 점이 열 대류의 특징이다. 6 | 지구 전체는 두꺼운 공기층에 싸여 있다. 7 | 물이나 공기는 대기의 열로 따뜻해져서 활발하게 대류를 이루고 있다. 8 | 이것들이 해류도 되고 바람이 된다. 9 | 이에 의해서 열이 이동하므로 바닷물의 온도와 기온이 지구 위에서 고르게 되어 어떤 곳은 온도가 극도로 높다든다 낮다든가 하는 현상은 없다. 10 | 이 때문에 지구는 공기과 물이 없는 달 등에 비하면 훨씬 살기 좋은 환경에 있는 것이다. 11 | 12 | 물의 가열 13 | 물의 가열은 에너지원을 사용하여 초기 온도보다 높은 온도로 물을 가열하는 전열 과정이다. 14 | 시험관에 물을 반쯤 넣고 밑바닥쪽을 고정시킨 채 물의 윗부분만을 가열하면 윗쪽의 물이 끓는다. 15 | 그러나 바닥 쪽은 가열되지 않아서 그대로 차갑다. 16 | 만약 시험관 대신 구리 막대를 사용해서 같은 실험을 하면, 윗부분만 가열해도 아랫 부분은 손으로 잡을 수 없을 만큼 뜨거워진다. 17 | 이 두 현상의 차이는 물이 구리에 비해서 열의 전달이 좋지 않기 때문이다. 18 | 구리와 물의 열전도율을 비교하면 구리의 열전도율은 물의 약 1000배이다. 19 | 반대로 말하면 물은 구리의 약 100분의 1밖에 열은 전달하지 않는 것이 된다. 20 | 따라서 열전도만으로 시험관 속의 물을 가열하기는 매우 어렵다. 21 | 그러나 시험관의 물도 밑바닥에서 가열하면 전체가 고르게 더워지고, 이윽고 끓게 된다. 22 | 23 | 피막이아과 24 | 피막이아과(---亞科, )는 두릅나무과의 아과이다. 25 | 26 | 온도 측정 27 | 온도 측정(溫度測定, temperature measurement, thermometry)은 즉각적인 평가 또는 나중에 평가하기 위해 현재의 지역 온도를 측정하는 과정을 말한다. 28 | 표준화된 관련 측정으로 구성된 데이터셋을 사용하여 온도 추이를 평가할 수 있다. 29 | 표준화된 온도 측정을 시도한 일은 17세기 이전이었다. 30 | 예를 들어 기원후 170년, 물리학자 갈레노스는 얼음과 끓는 물을 동등한 비율로 섞어서 중립적인 온도 표준을 만들어냈다. 31 | 온도를 측정하려면 물체의 특별한 상태의 변화와 규칙적인 열 팽창을 이용한다. 32 | 보통 사용되는 온도계에는 섭씨 온도 눈금이 표시되어 있다. 33 | 이 온도 눈금은 1742년 스웨덴의 물리학자 셀시우스에 의해서 정해진 것으로, 이것을 나타내는데 30도 C라든가 30℃와 같은 C의 기호를 붙인다. 34 | 이외에 화씨 온도나 절대 온도가 온도 측정에 사용된다. 35 | 섭씨 온도는 다음과 같이 해서 정해지고 있다. 36 | 즉, 얼음이 녹는 온도를 0℃로 하고 또 1기압의 대기 속에서 물이 끓는 온도를 100℃로 결정하고, 0℃와 100℃ 사이를 100등분해서 그것을 1℃로 정하고 있다. 37 | 화씨 온도는 독일의 물리학자 파렌하이트가 1724년에 고안한 것으로, 이 온도를 나타낼 때는 F의 기호를 붙인다. 38 | 화씨 온도에 있어서는 얼음이 녹는 온도를 32℉, 물이 끓는 온도를 212℉로 하고 그 사이를 180등분 해서 1℉로 정하고 있다. 39 | 40 | 평형력 41 | 평형력(平衡力, equilibrant force)은 물체를 정적 평형 상태로 옮기는 힘이다. 42 | 하나의 물체에 여러 가지 힘이 동시에 작용하고, 물체가 정지하거나 또는 등속도 운동을 하고 있을 때, 이러한 힘들은 균형되어 있다고 한다. 43 | 하나의 물체에 작용하는 힘이 동일선상에 있으며, 크기가 같고, 방향이 반대일 때, 이 두 힘은 균형을 이룬다. 44 | 이 경우 두 힘이 동일한 점에 작용하지 않아도 된다. 45 | 어느 쪽으로도 움직이지 않아 승부가 나지 않을 때의 줄다리기나 막대 밀기가 이 예이다. 46 | 47 | 베사라비아 관구 대교구 48 | 베사라비아 관구 대교구 (Mitropolia Basarabiei)는 몰도바에 소재하는 루마니아 정교회의 자치 교회이다. 49 | 관할구역은 몰도바 공화국의 영토로 몰도바인과 루마니아 디아스포라를 대상으로 사목하고있다. 50 | 베사라비아 정교회라고도 한다. 51 | 베사라비아 관구 대교구는 1918년 키시너우 교구로 설립되었고, 1927년 수도 대교구가 되었다. 52 | 소련이 베사라비아 지역을 점령하고 몰도바 소비에트 사회주의 공화국(1944-1991)이 통치를 할 때는 공산주의의 영향으로 교회 활동이 위축되었다. 53 | 1992년 9월 14일 베사라비아의 수도 대교구가 지위를 회복하였고 1995년 관구 대교구로 승격되었다. 54 | 현재의 베사라비아 관구 대주교는 페트루(Petru)이다. 55 | 56 | FC 서울 2020 시즌 57 | FC 서울의 2020 시즌은 창단 후 37번째 시즌이자 최용수 감독의 2기 3년차 시즌이다. 58 | FC 서울 공식 웹사이트 일정 및 결과 59 | 2020 시즌 선수 등록을 완료한 모든 FC 서울 선수 60 | ※ (대후) 표기는 우선지명으로 기 선발된 후 대학에 진학하여 중퇴 및 졸업 후 당해 연도에 입단하는 선수를 의미한다. 61 | ※ (대) 표기는 우선지명으로 선발은 되었지만 당해 연도에 입단하지 않고 대학 진학 후 입단하는 선수를 의미한다. 62 | ※ (직) 표기는 우선지명으로 선발되어 고등학교 졸업 후 당해 연도에 직행으로 입단하는 선수를 의미한다. 63 | ※ (미) 표기는 우선지명으로 선발되었지만 당해 연도 직행 입단 혹은 대학 진학 후 입단 등을 결정하지 못한 진로 미정인 선수를 의미한다. 64 | 65 | 길이의 단위 66 | 길이의 단위는 길이 측정을 위해 쓰이는 임의로 선택된 기준이나 수용된 참조 기준을 말한다. 67 | 길이·시간·무게·온도 등 갖가지 물리량 중에서 가장 간단하게 측정되는 것이 길이이다. 68 | 길이에 대한 단위가 필요하게 된 원인의 하나는 농경지나 거주지의 경계선을 확정하기 위해서였을 것이다. 69 | 현재 영국과 미국 등에서는 관례적으로 푸트가 사용되고 있는데, 이는 사람의 발길이에 유래하고 있다. 고대의 문명이 발달한 지방에서의 단위도 오늘날의 푸트와 같은 정도였을 것이다. 70 | 그 이유는 기구가 없더라도 걸음으로써 간단히 측정할 수 있다는 점과, 택지나 농경지 따위는 푸트를 단위로 하여도 무방하기 때문이었을 것이다. 71 | 한편, 우리나라를 비롯한 중국·일본 등은 예부터 '척'으로 길이의 단위로 삼아 왔으나 현대에는 계량법에 의거, 미터법을 사용하고 있다. 72 | 73 | 필립 리브 74 | 필립 리브(, 1966년 2월 28일 ~ )은 영국의 판타지 · 아동 문학 작가이다. 75 | 76 | 성 삼위일체 대성당 (뉴욕) 77 | 성 삼위일체 대성당(Archdiocesan Cathedral of the Holy Trinity)은 미국 뉴욕 시 어퍼이스트사이드에 위치한 동방 정교회 성당이다. 78 | 콘스탄티노폴리스 총대주교청 미국 그리스 정교회 관구 대교구에 소속되어 있다. 79 | 1891년에 준공되었고 미국에서 두 번째로 설립된 그리스 정교회 사목구이고 뉴욕에서는 첫 번째로 설립된 정교회 사목구이다. 80 | 그리고 서반구에서는 가장 규모가 큰 동방 정교회 교회이다. 81 | 82 | 배설관 83 | 배설관(排泄管), 배출관(排出管), 신관은 척추동물의 콩팥과 비슷한 기능을 수행하는, 한 쌍으로 발견되는 무척추동물의 장기이다. 84 | 원신관(原腎管)은 다세포 동물에서 볼 수 있는 가장 원시적인 배설 기관으로, 편형동물·유형동물·윤형동물 등에서 볼 수 있다. 85 | 이것은 몸의 좌우로 뻗어 있는 주된 관에서 나뭇가지 모양의 가는 관이 몸의 곳곳에 분포하고 있다. 86 | 그 관의 끝에는 불꽃 세포가 있는데, 여기에서 노폐물을 걸러 세관에 이어지는 배설공으로 배출한다. 87 | 불꽃 세포는 깔때기 모양으로 퍼진 큰 세포로, 그 안에는 신축성이 있는 편모의 다발이 있어서, 그 운동으로 노폐물이 세관 내로 유도되는데, 편모 다발의 운동이 마치 불꽃이 흔들리는 것처럼 보인다고 하여 불꽃 세포라 불린다. 88 | 89 | 원 웨이 티켓 90 | 원 웨이 티켓(one-way ticket)은 다음을 의미한다. 91 | 92 | 에로틱 타잔 93 | 《에로틱 타잔》(Jungle Heat, Tarzan-X: Shame Of Jane, Tharzan - La vera storia del figlio della giungla)은 이탈리아에서 제작된 조 다마토 감독의 1994년 드라마 영화이다. 94 | 로코 시프레디 등이 주연으로 출연하였다. 95 | 96 | 교회 해체와 젠더 이데올로기 97 | 《교회 해체와 젠더 이데올로기》(The Destruction of Church and Gender Ideology)는 이정훈이 저술한 책이다. 98 | 2018년 1월 30일 킹덤북스에서 출간되었다. 99 | 책의 목차는 아래와 같다. 100 | 101 | 우익청년 윤성호 102 | 《우익청년 윤성호》(Seongho, The Right wing boy)는 한국에서 제작된 윤성호 감독의 2004년 다큐멘터리 영화이다. 103 | 독립영화인 국가보안법철폐 프로젝트라는 이름으로도 알려져 있다. 104 | 105 | 이효종씨 가족의 저녁식사 106 | 《이효종씨 가족의 저녁식사》(Dinner At Lee's House)는 한국에서 제작된 정희성 감독의 2003년 영화이다. 107 | 한국영화아카데미 등이 제작에 참여하였다. 108 | 109 | 완전한 사육 2007 110 | 《완전한 사육 2007》(Love education, )은 홍콩에서 제작된 오문증 감독의 2007년 스릴러, 공포 영화이다. 111 | 사카가미 카오리 등이 주연으로 출연하였다. 112 | 113 | 죄의 기독교적 관점 114 | 기독교의 기본 교리는 그리스도 품에서의 속죄이기에, 죄의 교리는 기독교의 중심이다. 115 | 죄에 관한 연구이자 기독교 신학의 한 분야인 죄악론 (罪惡論)은, 죄를 하느님의 인격과 기독교 성경법을 멸시하고 다른 사람들을 해치는 그에게의 범죄 행위로 묘사한다. 116 | 기독교인 입장에서 볼 때 이는 인간의 합리적 성질뿐만 아니라 하느님의 본성과 그의 영원한 율법을 위반하는 악한 인간 행위이다. 117 | 성 아우구스티누스의 고전적 정의에 따르면 "하느님의 영원한 율법에 반대하는 말, 행동 또는 욕망"이다. 118 | 기독교 죄악론은 자연법, 기독교 윤리의 개념과 밀접한 관련이 있다. 119 | 일부 학자들 가운데서, 죄는 구속력이 없는 철학적 틀과 기독교 윤리의 관점에 대한 법적 위반 또는 계약 위반으로 이해되며, 따라서 구원은 법적인 용어로 여겨지는 경향이 있다. 120 | 후에 아우구스티누스가 펠라기우스주의자들과의 토론에서 제기했듯이, 다른 기독교 학자들은 죄가 근본적으로 기독교 신에 대한 사랑의 상실과 자애의 증가와 관계 있다고 이해한다. 121 | 죄의 법적 정의와 마찬가지로, 이 정의는 기독교적 은혜와 구원에 대한 이해에도 영향을 미치며, 따라서 관계적 용어로 볼 수 있다. 122 | 123 | 미나리아과 124 | 미나리아과(---亞科, )는 미나리과의 아과이다. 125 | 126 | 인텔리레온 127 | 인텔리레온은 8세대 가라르지방을 배경으로 한 포켓몬스터 소드실드 스타팅 포켓몬들중 물타입 울머기의 최종진화채이다. 128 | 인텔리레온은 도마뱀과 스파이를 모티브로 하여 둘을 결합시킨 형태이다. 129 | 그리고 다이맥스 후에 공격할땐 자신의 한 손을 마치 스파이의 총 모양으로 만들어 공격한다. 130 | 전용기도 노려맞히기라는 기술로 스파이 포켓몬이 쓸만한 기술이다. 131 | 132 | 고수족 133 | 고수족(--族, )은 미나리아과의 족이다. 134 | 135 | 미정의 값 136 | 컴퓨팅(특히 프로그래밍에서) 미정의 값은 문법적으로 유효함에도 불구하고 식이 올바른 값을 가지고 있지 않은 상태이다. 137 | 미정의 값은 빈 문자열, 불리언의 "false", 또는 정의되었으나 비어있는 값과는 구별된다. 138 | 상황에 따라 미정의 값을 평가할 때 예외나 미정의 동작을 일으킬 수 있으며 일부 프로그래밍 언어에서 미정의 값은 예측할만한 일반적인 프로그램 실행 중에 발생할 수 있다. 139 | 동적 자료형 언어들은 일반적으로 미정의 값을 가능하면 명시적으로 처리한다. 140 | 이를테면 펄은 codice_1 연산자가 있어서 이러한 값을 변수로 "할당"할 수 있다. 141 | 다른 형 체계에서 미정의 값은 알 수 없고 예측하지 못하는 값을 의미할 수 있으며 평가 시도 시 프로그램 실패를 일으킬 수 있다. 142 | 143 | 사나이 부르스 144 | 《사나이 부르스》는 한국에서 제작된 김영걸 감독의 1969년 영화이다. 145 | 박노식 등이 주연으로 출연하였고 차태진 등이 제작에 참여하였다. 146 | 147 | 비애 148 | 비애는 다음을 의미한다. 149 | 150 | 비애 (1952년 영화) 151 | 《비애》(Ruby Gentry)는 미국에서 제작된 킹 비더 감독의 1952년 드라마, 멜로/로맨스 영화이다. 152 | 제니퍼 존스 등이 주연으로 출연하였다. 153 | 154 | 비애 (1990년 영화) 155 | 《비애》(La Putain Du Roi, The King's Whore)는 영국에서 제작된 엑셀 코티 감독의 1990년 드라마 영화이다. 티모시 달튼 등이 주연으로 출연하였고 모리스 베르나르트 등이 제작에 참여하였다. 1990년 칸 영화제에 출품되었다. 156 | 157 | 원산지관리사 158 | 무역분야 자격증 159 | ・ 관세사 160 | ・ 원산지관리사 161 | ・ 보세사 162 | ・ 물류관리사 163 | ・ 국제무역사 164 | ・ 무역영어 165 | ・ 유통관리사 166 | ・ 무역관리사 167 | 국가전문인력채용 지원금 대상자격 168 | ・ 변호사 169 | ・ 변리사 170 | ・ 세무사 171 | ・ 관세사 172 | ・ 경영지도사 173 | ・ 원산지관리사 174 | ・ 공인노무사 175 | ・ 공인회계사 176 | 2010년 6월 제1기 원산지관리사 시험시행하여 2019년 12월 현재, 27기 원산지관리사를 배출. 177 | 2012년 12월27일 관세청으로부터 국가공인을 획득 한 7년차 국가공인자격이다. 178 | 원산지관리사의 업무는 크게 다음과 같다. 179 | 1. 원산지관리사는 FTA 발효국가와 무역거래기업, 관련국가 물류업체들에게 FTA 특혜관세혜택을 누릴 수 있도록 지식서비스를 제공한다. 180 | 2. 원산지관리사는 수출입관련 기업 현장에서 사업기획, 생산 및 구매전략, 원산지관리실무, 원산지 관리시스템 운영 등의 직무를 수행한다. 181 | 3. 원산지관리사는 FTA 특혜관세 혜택을 향유하기 위해, 전략적 수출지역 선정 및 체약국별 원가개선효과를 분석하고, 글로벌 생산과 조달 네트워크를 구축한다. 182 | 관세청이 국제원산지정보원으로 시행을 위임하면서 원산지관리사 뿐만아니라 실무에 포커스를 맞춘 원산지실무사의 시험도 국제원산지정보원이 시험을 주관한다. 183 | 시험은 1년에 통상 2회실시. 184 | 국가공인을 획득 한 해인 2012년부터 초반까지는 연3회 실시한 해도 있었으나, 어느순간 다시 연2회로 굳어졌다. 185 | FTA 특혜관세 수요에 따라 국가가 합격자 TO를 조절하고 있다는 평. 186 | 비교적 무난한 난이도로 고득점 할 수 있는 과목. FTA 관련법령의 암기가 필요하다. 187 | FTA협정의 경우 매년 추가되고 있으므로 암기해야 할 법령 또한 늘어난다. 188 | 한국의 경우 FTA를 공격적으로 추진하고 있는 국가이므로 원산지관리사를 취득하려면 추가적인 협정이 늘어나기전에 빨리 취득하는 것이 이득. 말장난이 심하기 때문에 수험자에따라서 의외로 어려워 하는 수험자도 적지 않은편. 벼락치기나 속독을 통한 유추학습이 잘 안통하는 시험이므로 충분한 이해를 바탕으로 한 꼼꼼한 반복회독이 필요하다. 189 | 원산지관리사에서 과락이 가장 많이 발생하는 자타공인 킬링파트. 97개의 류와 5,000개 이상의 호를 달달달 외워야만 하는 과목이다. 190 | 그리고 HS-CODE가 변환되는 세번변경통칙은 씹어먹을 수준으로 이해를 해야 손을 댈 수 있는 과목. 관세사 2차시험에나 나올법한 내용들이 원산지관리사의 품목분류 파트에서 공부를 해야한다. 191 | 여기서 많은 수강생들이 포기하며 실제로 과락율 또한 매우 높은 수준. 특히 한국의 주력산업인 자동차, 전자, 철강, 기계류부분은 호까지 완벽하게 암기하지 않으면 과락을 면하지 못할 가능성이 높다. 192 | 각 협정별 원산지결정기준 등 법률조항과 규칙등의 암기와 이해가 필요하다. 193 | 특히 계산문제들이 점점 까다로워지고 있으며 아예 교재에서는 전략적으로계산문제는 패스 해버리라고 나와있다. 194 | 충분한 이해를 통한 암기가 이루어지지 않을 경우 풀 수 없는 문제들이 많아 꼼꼼한 공부가 필요하다. 195 | 품목분류만큼은 아니지만 수험생들이 적잖히 고전하는 과목. 196 | 무역관련 전공자라면 조금 공부하면 고득점이 가능한 과목이다. 197 | 평이한 난이도의 암기문제가 대부분이나 중간중간 등장하는 세율 및 금액계산과 날짜계산 문제는 상당히 골치아프다. 198 | 199 | 꿩먹고 알먹고 200 | 《꿩먹고 알먹고》는 한국에서 제작된 심우섭 감독의 1966년 영화이다. 201 | 서영춘 등이 주연으로 출연하였고 박의순 등이 제작에 참여하였다. 202 | 203 | 수정탕 둘째 딸 204 | 《수정탕 둘째 딸》(Good Yeon-Ha)는 한국에서 제작된 박이웅 감독의 2008년 영화이다. 205 | 한지율 등이 주연으로 출연하였고 황선영 등이 제작에 참여하였다. 206 | 207 | 눈 감으면 보이는 세상 208 | 《눈 감으면 보이는 세상》은 한국에서 제작된 배경윤 감독의 1996년 영화이다. 209 | 오광록 등이 주연으로 출연하였고 배경윤 등이 제작에 참여하였다. 210 | 211 | 대결투 212 | 대결투는 다음을 의미한다. 213 | 214 | 대결투 (1971년 영화) 215 | 《대결투》(大決鬥, The Duel)는 홍콩에서 제작된 장철 감독의 1971년 액션, 드라마 영화이다. 216 | 적룡 등이 주연으로 출연하였다. 217 | 218 | 호소자 219 | 《호소자》(好小子, Young Dragons: Kung Fu Kids)는 타이완에서 제작된 장미군 감독의 1986년 액션 영화이다. 220 | 안정국 등이 주연으로 출연하였다. 221 | 222 | 그들에겐 각자의 몫이 있다 223 | 《그들에겐 각자의 몫이 있다 224 | 》(To Each His Own)는 미국에서 제작된 밋첼 레이슨 감독의 1946년 영화이다. 225 | 올리비아 드 하빌랜드 등이 주연으로 출연하였고 찰스 브래킷 등이 제작에 참여하였다. 226 | 227 | 급동기협 228 | 《급동기협》(急凍奇俠: Iceman Cometh)은 홍콩에서 제작된 곽요량 감독의 1989년 영화이다. 229 | 원표 등이 주연으로 출연하였고 추문회 등이 제작에 참여하였다. 230 | 출시명은 청옥불이다. 231 | 232 | 호스 위스퍼러 233 | 《호스 위스퍼러》(The Horse Whisperer)는 미국에서 제작된 로버트 레드포드 감독의 1998년 드라마, 멜로/로맨스 영화이다. 234 | 로버트 레드포드 등이 주연으로 출연하였고 패트릭 마키 등이 제작에 참여하였다. 235 | 236 | 웅이 이야기 237 | 《웅이 이야기》(Woong's Story)는 한국에서 제작된 이하송 감독의 2007년 드라마, 가족 영화이다. 김우석 등이 주연으로 출연하였다. 238 | 239 | 행복의 조건 240 | 행복의 조건은 다음을 의미한다. 241 | 242 | 행복의 조건 (1959년 영화) 243 | 《행복의 조건》는 한국에서 제작된 이봉래 감독의 1959년 영화이다. 244 | 윤일봉 등이 주연으로 출연하였고 이래원 등이 제작에 참여하였다. 245 | 246 | 화류춘몽 247 | 《화류춘몽》은 한국에서 제작된 박성복 감독의 1958년 영화이다. 248 | 최봉 등이 주연으로 출연하였고 최일 등이 제작에 참여하였다. 249 | 250 | 영구와 땡칠이 2 251 | 《영구와 땡칠이 2 - 소림사 가다》(영구와 땡칠이 소림사 가다: Yong-Gu And Taeng-Chiri Go To Sorim Temple)는 한국에서 제작된 남기남 감독의 1989년 가족, 모험, 액션, 코미디 영화이다. 252 | 심형래 등이 주연으로 출연하였고 정욱 등이 제작에 참여하였다. 253 | 254 | 삼천포 아가씨 255 | 《삼천포 아가씨》는 한국에서 제작된 강찬우 감독의 1966년 영화이다. 256 | 황정순 등이 주연으로 출연하였고 김태현 등이 제작에 참여하였다. 257 | 258 | 여대생의 첫 욕망 259 | 《여대생의 첫 욕망》(Premiers Desirs, First Desires)은 프랑스에서 제작된 데이비드 해밀턴 감독의 1983년 드라마, 멜로/로맨스 영화이다. 260 | 모니카 브로에크 등이 주연으로 출연하였고 알레인 테르지안 등이 제작에 참여하였다. 261 | 262 | 은하에서 온 별똥왕자 3 - 은하열차 88 263 | 《은하에서 온 별똥왕자 3 - 은하열차 88》(The Meteor Prince From The Milky Way 3)는 한국에서 제작된 석도원 감독의 1988년 영화이다. 264 | 이건주 등이 주연으로 출연하였고 박재홍 등이 제작에 참여하였다. 265 | 266 | 달과 꼭지 267 | 《달과 꼭지》(La Teta Y La Luna, The Tit And The Moon)는 프랑스에서 제작된 비가스 루나 감독의 1994년 코미디 영화이다. 268 | 비엘 듀란 등이 주연으로 출연하였고 안드레스 빈센테 고메스 등이 제작에 참여하였다. 269 | 270 | 매화방 천둥불 271 | 《매화방 천둥불》(Light Of Maehwabang)는 한국에서 제작된 이광섭 감독의 1989년 멜로/로맨스 영화이다. 272 | 한명구 등이 주연으로 출연하였고 김원두 등이 제작에 참여하였다. 273 | 274 | 평양 기생 275 | 《평양 기생》은 한국에서 제작된 이규웅 감독의 1966년 영화이다. 276 | 신영균 등이 주연으로 출연하였고 이수길 등이 제작에 참여하였다. 277 | 278 | 죽는 자를 위한 기도 279 | 《죽는 자를 위한 기도》(A Prayer For The Dying)는 미국에서 제작된 마이크 호지스 감독의 1987년 액션, 드라마 영화이다. 280 | 미키 루크 등이 주연으로 출연하였고 사무엘 골드윈 주니어 등이 제작에 참여하였다. 281 | 282 | 투 문 정션 2 283 | 《투 문 정션 2》(Return To Two Moon Junction)는 미국에서 제작된 파하드 맨 감독의 1995년 영화이다. 284 | 멜린다 285 | 클락 등이 주연으로 출연하였고 멜 펄 등이 제작에 참여하였다. 286 | 287 | 백 투 백 288 | 백 투 백(Back to Back, back-to-back)은 다음을 의미한다. 289 | 290 | 아메리칸 신디케이트 2 - 백 투 백 291 | 《아메리칸 신디케이트 2 - 백 투 백》(Back To Back)는 미국에서 제작된 로저 나이거드 감독의 1996년 액션, 드라마 영화이다. 292 | 마이클 루커 등이 주연으로 출연하였고 아키 코민 등이 제작에 참여하였다. 293 | 294 | 자매의 화원 295 | 《자매의 화원》(A Sister's Garden)는 한국에서 제작된 신상옥 감독의 1959년 드라마 영화이다. 최은희 등이 주연으로 출연하였고 신상옥 등이 제작에 참여하였다. 1959년 개봉 후 2018년 2월 26일 대한민국에서 재개봉되었다. 296 | 297 | 하노버 스트리트 298 | 《하노버 스트리트》(Hanover Street)는 영국에서 제작된 피터 하이암스 감독의 1979년 드라마, 액션, 모험, 멜로/로맨스 영화이다. 299 | 해리슨 포드 등이 주연으로 출연하였고 폴 라자러스 3세 등이 제작에 참여하였다. 300 | 301 | 여자 19세 302 | 《여자 19세》는 한국에서 제작된 김수용 감독의 1964년 영화이다. 303 | 강신성일 등이 주연으로 출연하였고 백완 등이 제작에 참여하였다. 304 | 305 | 악마 같은 여자 306 | 《악마 같은 여자》(Saving Silverman)는 미국에서 제작된 데니스 듀간 감독의 2001년 코미디 영화이다. 307 | 제이슨 빅스 등이 주연으로 출연하였다. 308 | 309 | 하얀 면사포 310 | 《하얀 면사포》(Noce Blanche, White Wedding)는 프랑스에서 제작된 장-클로드 브리소 감독의 1989년 드라마, 멜로/로맨스 영화이다. 311 | 바네사 파라디 등이 주연으로 출연하였고 마가렛 메네고즈 등이 제작에 참여하였다. 312 | 313 | 월급봉투 314 | 《월급봉투》는 한국에서 제작된 김수용 감독의 1964년 영화이다. 315 | 신영균 등이 주연으로 출연하였고 박원석 등이 제작에 참여하였다. 316 | 317 | 남자는 괴로워 318 | 남자는 괴로워는 다음을 의미한다. 319 | 320 | 남자는 괴로워 (1973년 영화) 321 | 《남자는 괴로워》(L'Evenement Le Plus Important Depuis Que L'Homme A Marche Sur La Lune)는 이탈리아에서 제작된 자크 데미 감독의 1973년 영화이다. 322 | 까뜨린느 드뇌브 등이 주연으로 출연하였다. 323 | 324 | 사귀는 사람 있니 325 | 《사귀는 사람 있니》(Are You Seeing Anyone)는 한국에서 제작된 김형주 감독의 2002년 드라마, 멜로/로맨스 영화이다. 326 | 김태훈 등이 주연으로 출연하였다. 327 | 328 | 노란 샤쓰 입은 사나이 329 | 《노란 샤쓰 입은 사나이》는 한국에서 제작된 엄심호 감독의 1962년 영화이다. 330 | 신영균 등이 주연으로 출연하였고 차태진 등이 제작에 참여하였다. 331 | 332 | 구타 유발자... 333 | 잠들다 334 | 《구타 유발자... 335 | 잠들다》(Four Million Blows)는 한국에서 제작된 유정현 감독의 1999년 영화이다. 336 | 유정현 등이 주연으로 출연하였다. 337 | 338 | 아랑 드롱의 조로 339 | 《조로》(Zorro)는 이탈리아, 프랑스에서 제작된 듀시오 테사리 감독의 1975년 모험, 서부 영화이다. 340 | 알랭 들롱 등이 주연으로 출연하였고 루치아노 마르티노 등이 제작에 참여하였다. 341 | 342 | 가리베가스 343 | 《가리베가스》(Garivegas)는 한국에서 제작된 김선민 감독의 2005년 영화이다. 344 | 이윤미 등이 주연으로 출연하였다. 345 | 346 | 사랑도 흥정이 되나요? 347 | 《사랑도 흥정이 되나요? 348 | 》(Combien Tu M'Aimes?, How Much Do You Love Me?)는 프랑스에서 제작된 베르뜨랑 블리에 감독의 2005년 코미디, 드라마, 멜로/로맨스 영화이다. 모니카 벨루치 등이 주연으로 출연하였고 올리비에 델보스크 등이 제작에 참여하였다. 349 | 350 | 놀부 흥부 351 | 《놀부 흥부》는 한국에서 제작된 김조성 감독의 1925년 영화이다. 352 | 문수일 등이 주연으로 출연하였고 하야가와 고슈 등이 제작에 참여하였다. 353 | 354 | 배우 수업 355 | 배우 수업은 다음을 뜻한다. 356 | 357 | 배우 수업 (1978년 영화) 358 | 《배우 수업》은 한국에서 제작된 이형표 감독의 1978년 영화이다. 359 | 이대근 등이 주연으로 출연하였고 강대진 등이 제작에 참여하였다. 360 | 361 | 작은 이야기 362 | 《작은 이야기》(Small Story)는 한국에서 제작된 진영기 감독의 2002년 멜로/로맨스 영화이다. 363 | 박치화 등이 주연으로 출연하였다. 364 | 365 | 누가 해변에서 함부로 불꽃놀이를 하는가 366 | 《누가 해변에서 함부로 불꽃놀이를 하는가》는 한국에서 제작된 조여래 감독의 2008년 드라마 영화이다. 367 | 백승현 등이 주연으로 출연하였고 최선용 등이 제작에 참여하였다. 368 | 369 | 3일 간의 전쟁 370 | 3일 간의 전쟁은 다음을 의미한다. 371 | 372 | 내일은 뭐 할거니 373 | 《내일은 뭐 할거니》는 한국에서 제작된 이봉원 감독의 1986년 영화이다. 374 | 강석현 등이 주연으로 출연하였고 이봉원 등이 제작에 참여하였다. 375 | 376 | 꿈꾸는 식물 377 | 《꿈꾸는 식물》(Dreaming Plant)은 한국에서 제작된 최기풍 감독의 1990년 멜로/로맨스 영화이다. 378 | 김진화 등이 주연으로 출연하였고 임종구 등이 제작에 참여하였다. 379 | 380 | 리크텐스테이니아속 381 | 리크텐스테이니아속(lichtensteinia屬, )은 미나리아과의 단형 족인 리크텐스테이니아족(lichtensteinia族, )에 속하는 유일한 속이다. 382 | 속명은 독일의 생물학자인 마르틴 힌리히 리히텐슈타인(Martin Hinrich Lichtenstein)의 이름을 따 지어졌다. 383 | 384 | 캉캉 69 385 | 《캉캉 69》는 한국에서 제작된 석도원 감독의 1992년 에로, 멜로/로맨스, 드라마 영화이다. 386 | 유연실 등이 주연으로 출연하였고 강미영 등이 제작에 참여하였다. 387 | 388 | 거친 녀석들 389 | 거친 녀석들은 다음을 의미한다. 390 | 391 | 거친 녀석들 (2007년 영화) 392 | 《거친 녀석들》(Wild Hogs)은 미국에서 제작된 월트 벡커 감독의 2007년 모험, 코미디 영화이다. 393 | 팀 알렌 등이 주연으로 출연하였고 브라이언 로빈스 등이 제작에 참여하였다. 394 | 395 | 배꼽 버스 396 | 《배꼽 버스》는 한국에서 제작된 박광우 감독의 1995년 코미디, 멜로/로맨스 영화이다. 397 | 김수정 등이 주연으로 출연하였고 김보식 등이 제작에 참여하였다. 398 | 399 | 무도회의 수첩 400 | 《무도회의 수첩》(Un Carnet De Bal, Dance Of Life)는 프랑스에서 제작된 줄리앙 뒤비비에르 감독의 1937년 영화이다. 401 | 아리 보르 등이 주연으로 출연하였다. 402 | 403 | 불타는 김 대리의 밤 404 | 《불타는 김 대리의 밤》(Mr. Kim's Burning Night)은 한국에서 제작된 공부성 감독의 2007년 드라마, 코미디 영화이다. 박재현 등이 주연으로 출연하였다. 405 | 406 | 별 3형제 407 | 《별 3형제》는 한국에서 제작된 김기 감독의 1977년 영화이다. 408 | 전호진 등이 주연으로 출연하였고 이전철 등이 제작에 참여하였다. 409 | 410 | 오버 미 411 | 《오버 미》(Over Me)는 한국에서 제작된 임창재 감독의 1996년 영화이다. 412 | 이용이 등이 주연으로 출연하였고 임창재 등이 제작에 참여하였다. 413 | 414 | 웬일이니 415 | 《웬일이니》는 한국에서 제작된 진준랑 감독의 1983년 영화이다. 416 | 하원 등이 주연으로 출연하였고 정창화 등이 제작에 참여하였다. 417 | 418 | 마를로티엘라 419 | 마를로티엘라(marlothiella, )는 미나리아과의 단형 족인 마를로티엘라족(marlothiella族, )의 단형 속인 마를로티엘라속(marlothiella屬, )에 속하는 유일한 종이다. 420 | 나미비아에 분포한다. 421 | 422 | 임 그리워 423 | 《임 그리워》는 한국에서 제작된 고영남 감독의 1970년 영화이다. 424 | 최무룡 등이 주연으로 출연하였고 전석진 등이 제작에 참여하였다. 425 | 426 | 이자벨 에버하트 427 | 《이자벨 에버하트》(Isabelle Eberhardt)는 프랑스에서 제작된 이안 프링글 감독의 1991년 드라마 영화이다. 428 | 마틸다 메이 등이 주연으로 출연하였고 다니엘 샤프 등이 제작에 참여하였다. 429 | 430 | 하얀 외침 검은 태양 431 | 《하얀 외침 검은 태양》(Le Brasier)은 프랑스에서 제작된 에릭 바비에 감독의 1991년 드라마 영화이다. 432 | 마루츠카 데트메르스 등이 주연으로 출연하였다. 433 | 434 | 미나리족 435 | 미나리족(---族, )은 미나리아과의 족이다. 436 | 437 | 베로니카 게린 438 | 베로니카 게린(Veronica Guerin, 1958년 7월 5일 ~ 1996년 6월 26일)은 마약왕들에 의해 살해된, 아일랜드의 범죄를 알린 기자이다. 439 | 학교에 운동선수로 재학하였다가 나중에 아일랜드 축구, 농구팀에서 경기를 뛰었다. 440 | 회계를 공부한 뒤 7년 간 홍보 업무를 진행했고 그 뒤 피어너 팔에서 Seán Haughey의 선거 대리인으로 있었다. 441 | 1990년 기자가 되어 선데이 브즈니스 포스트와 선데이 트리뷴에 기사를 썼다. 442 | 1994년 선데이 인디펜던트에서 범죄에 관해 기사를 쓰기 시작했다. 443 | 1996년, 신호등에 멈춰서 있는 동안 치명적인 총상을 당했다. 444 | 이 총상은 아일랜드의 분노를 샀다. 445 | 그녀의 사망에 관한 조사 이후 수많은 체포와 유죄선고가 잇따랐다. 446 | 447 | 베로니카 게린 (영화) 448 | 《베로니카 게린》(Veronica Guerin)는 영국에서 제작된 조엘 슈마허 감독의 2003년 드라마 영화이다. 449 | 케이트 블란쳇 등이 주연으로 출연하였고 제리 브룩하이머 등이 제작에 참여하였다. 450 | 더블린의 마약 거래를 조사하다가 결국 1996년 37세의 나이로 죽임을 당한 아일랜드의 기자 베로니카 게린에 초점을 두고 있다. 451 | 452 | 테오레마 453 | 《테오레마》(Theorem, Teorema)는 이탈리아에서 제작된 피에르 파올로 파졸리니 감독의 1968년 드라마, 미스터리 영화이다. 454 | 실바나 망가노 등이 주연으로 출연하였고 마놀로 볼로그니니 등이 제작에 참여하였다. 455 | 456 | 잊을 수 없는 순간 457 | 《잊을 수 없는 순간》은 한국에서 제작된 이강윤 감독의 1985년 드라마 영화이다. 458 | 김덕영 등이 주연으로 출연하였고 정도환 등이 제작에 참여하였다. 459 | 460 | 우희준 461 | 우희준은 2018년 인도네시아 자카르타 아시안 게임 대한민국 국가대표 참가자 출신이고 동시에 2019년 대한민국 미스코리아 선(善) 출신이다. 462 | 463 | 위험한 남편 464 | 《위험한 남편》(危險한 男便)은 한국에서 제작된 이용민 감독의 1970년 영화이다. 465 | 남정임 등이 주연으로 출연하였고 주동진 등이 제작에 참여하였다. 466 | 467 | 윌리엄 캠벨 (1841년) 468 | 윌리엄 캠벨(William Campbell, 甘為霖, 1841년~1921년)은 청나라 말기 대만에서 선교 활동을 했던 스코틀랜드 출신의 장로교 선교사이다. 469 | 그는 대만과 관련된 주제에 대해 폭넓게 썼으며, 맹인학교도 설립했다. 470 | 그 섬의 초기 역사(특히 네덜란드 시대)에 관심이 많았던 당시 그의 지식은 “의심할 여지 없이 이 주제에서는 가장 위대한 권위자”라고 불릴 정도였다. 471 | 그는 일월담호를 보게 된 최초의 유럽인이었을 것이며, 그는 17세기 네덜란드 선교사 조지 칸디디우스를 기리기 위해, 그 호수를 칸디디우스호(Lake Candidius)라고 이름 지었다. 472 | 캠벨은 1871년 청나라가 다스리는 대만에 도착해 대만 남부(현대의 타이난)에 자리잡았고, 이 지역에서 한족과 대만 원주민을 모두에게 선교를 펼쳤다. 473 | 그는 대만에서 선교활동을 하던 토머스 바클레이, 제임스 레이드라프 맥스웰, 조지 레슬리 맥케이 등과 동시대의 사람이었다. 474 | ‘원주민 성직자’(즉 한족와 원주민 성직자들)의 가장 강력한 지지자였던 캠벨은 다음과 같은 한 특별한 사건에 대해 썼다. 475 | 캠벨은 청불 전쟁에 대한 기록을 남겼을 뿐만 아니라, 일본의 점령과 대만의 전환을 목격했다. 476 | 그의 선교는 그가 1917년 마지막으로 대만을 떠나 1921년 고향인 스코틀랜드로 돌아갈 때까지 46년간 지속되었다. 477 | 478 | 영광의 침실 479 | 《영광의 침실》은 한국에서 제작된 김응천 감독의 1959년 영화이다. 480 | 황해 등이 주연으로 출연하였고 김동식 등이 제작에 참여하였다. 481 | 482 | 미국 제18공수군단장 483 | 다음은 제18(XVIII)공수군단의 군단장의 목록이다. 484 | 485 | 둘 하나 섹스 486 | 《둘 하나 섹스》(Yellow Flower)는 한국에서 제작된 이지상 감독의 1998년 드라마 영화이다. 487 | 김중기 등이 주연으로 출연하였다. 488 | 489 | 버스를 타다 490 | 《버스를 타다》(Bus Stop)는 한국에서 제작된 주형진 감독의 2006년 드라마, 공포, 스릴러 영화이다. 491 | 하시은 등이 주연으로 출연하였다. 492 | 493 | 모의 법정 (영화) 494 | 《모의 법정》(Listen To Me)은 미국에서 제작된 더글러스 데이 스튜어트 감독의 1989년 영화이다. 495 | 크리스토퍼 앳킨스 등이 주연으로 출연하였다. 496 | 497 | 오부자 498 | 오부자는 다음을 의미한다. 499 | 500 | 오부자 (1969년 영화) 501 | 《오부자》(五父子, Father and Sons)는 한국에서 제작된 권철휘 감독의 1969년 코미디 영화이다. 502 | 김희갑 등이 주연으로 출연하였고 신상옥 등이 제작에 참여하였다. 503 | 504 | 구름 저편에 505 | 《구름 저편에》(Par-Dela Les Nuages, Beyond The Clouds)는 독일에서 제작된 감독미켈란젤로 안토니오니, 빔 벤더스 감독의 1995년 드라마, 멜로/로맨스 영화이다. 506 | 화니 아르당 등이 주연으로 출연하였고 필립 카카손 등이 제작에 참여하였다. 507 | 508 | 사랑의 파도 509 | 《사랑의 파도》(Sea Of Love)는 미국에서 제작된 해롤드 벡커 감독의 1989년 네오누아르 범죄, 스릴러, 드라마 영화이다. 510 | 알 파치노 등이 주연으로 출연하였고 마틴 브레그먼 등이 제작에 참여하였다. 511 | 512 | 나는 너를 천사라고 부른다 513 | 《나는 너를 천사라고 부른다》(I Call You Angel)는 한국에서 제작된 김인수 감독의 1992년 드라마 영화이다. 514 | 강리나 등이 주연으로 출연하였고 홍면유 등이 제작에 참여하였다. 515 | 516 | 소파 승진 517 | 《소파 승진》(Promotion Canape)은 프랑스에서 제작된 디디에 카민카 감독의 1990년 코미디 영화이다. 518 | 마르고 아바스칼 등이 주연으로 출연하였다. 519 | 520 | 검은 장갑 521 | 《검은 장갑》은 한국에서 제작된 김성민 감독의 1963년 영화이다. 522 | 박노식 등이 주연으로 출연하였고 오석조 등이 제작에 참여하였다. 523 | 524 | 미, 마이셀프 525 | 《미, 마이셀프》(ขอให้รักจงเจริญ, Me... Myself)는 태국에서 제작된 퐁파트 와치라번종 감독의 2007년 멜로/로맨스, 드라마, 코미디 영화이다. 526 | 아난다 에버링햄 등이 주연으로 출연하였고 피야락 마하타나삽 등이 제작에 참여하였다. 527 | 528 | 삽질, 텍사스 529 | 《삽질, 텍사스》(Shoveling, TEXAS)는 한국에서 제작된 성시흡 감독의 2008년 코미디, 판타지 영화이다. 530 | 안치욱 등이 주연으로 출연하였다. 531 | 532 | 에덴의 서쪽 533 | 《에덴의 서쪽》은 한국에서 제작된 권영순 감독의 1994년 드라마, 멜로/로맨스 영화이다. 534 | 문태선 등이 주연으로 출연하였고 K.Y. 림 등이 제작에 참여하였다. 535 | 536 | 지구여 멈춰라 내리고 싶다 537 | 《지구여 멈춰라 내리고 싶다 538 | 》는 한국에서 제작된 이재웅 감독의 1974년 멜로/로맨스 영화이다. 539 | 남진 등이 주연으로 출연하였고 이우석 등이 제작에 참여하였다. 540 | 541 | 연애할 시간 없다 542 | 《연애할 시간 없다 543 | 》는 한국에서 제작된 이종기 감독의 1964년 영화이다. 544 | 최지희 등이 주연으로 출연하였고 안태식 등이 제작에 참여하였다. 545 | 546 | 나도 연애할 수 있다 547 | 《나도 연애할 수 있다 548 | 》는 한국에서 제작된 임원직 감독의 1965년 영화이다. 549 | 김승호 등이 주연으로 출연하였고 홍의선 등이 제작에 참여하였다. 550 | 551 | 자전거를 타고 온 크리스마스 552 | 《자전거를 타고 온 크리스마스》(Christmas Comes On A Bicycle)는 한국에서 제작된 박선욱 감독의 2003년 드라마 영화이다. 553 | 김태우 등이 주연으로 출연하였다. 554 | 555 | 서스펙트 제로 556 | 《서스펙트 제로》(Suspect Zero)는 미국에서 제작된 E. 일라이어스 메리지 감독의 2004년 스릴러, 범죄, 공포, 드라마 영화이다. 557 | 아론 에크하트 등이 주연으로 출연하였고 게이 허쉬 등이 제작에 참여하였다. 558 | 559 | 애마와 변강쇠 560 | 《애마와 변강쇠》는 한국에서 제작된 김문옥 감독의 1995년 영화이다. 561 | 한명구 등이 주연으로 출연하였다. 562 | 563 | 나터러도마뱀붙이 564 | 나터러도마뱀붙이("Tropiocolotes nattereri" )는 나터러 게코(Natterer's gecko)라 불리며, 이집트, 이스라엘, 요르단, 사우디아라비아에 서식하는 종이다. 565 | 종명, "nattereri" 는 오스트리아의 조류학자 요한 나터러()를 기린 것이다. 566 | 나터러도마뱀붙이는 난생한다. 567 | 성적 이형성은 뚜렷하지 않으나, 칼슘낭을 확인하면 도움이 된다. 568 | 569 | 하드카바 570 | 《하드카바》(I, Madman)는 미국에서 제작된 티보 타카스 감독의 1989년 공포, 스릴러 영화이다. 571 | 제니 라이트 등이 주연으로 출연하였고 라파엘 아이슨먼 등이 제작에 참여하였다. 572 | 573 | 2022년 2월 574 | 575 | 576 | 577 | Memories (노래) 578 | "Memories"는 미국의 팝 록 밴드 마룬 5의 노래이다. 579 | 580 | 토요일 밤에 581 | 《토요일 밤에》는 한국에서 제작된 이성구 감독의 1974년 드라마 영화이다. 582 | 신일룡 등이 주연으로 출연하였고 한갑진 등이 제작에 참여하였다. 583 | 584 | 포스 맨 585 | 《포스 맨》(De Vierde Man, The Fourth Man)은 네덜란드에서 제작된 폴 버호벤 감독의 1983년 드라마, 미스터리, 스릴러 영화이다. 586 | 예로엔 크라베 등이 주연으로 출연하였고 롭 휴베르 등이 제작에 참여하였다. 587 | 588 | 대삼원 589 | 《대삼원》(大三元: Tristar)은 홍콩에서 제작된 서극 감독의 1996년 액션, 멜로/로맨스 영화이다. 590 | 장국영 등이 주연으로 출연하였고 왕응상 등이 제작에 참여하였다. 591 | 592 | Without Me (할시의 노래) 593 | "Without Me"는 미국의 가수 할시의 노래이다. 594 | 595 | 안녕, 쿠로 596 | 《안녕, 쿠로》(さよなら, クロ, Sayonara, Kuro)는 일본에서 제작된 마츠오카 조지 감독의 2003년 드라마 영화이다. 597 | 츠마부키 사토시 등이 주연으로 출연하였고 토야 노부유키 등이 제작에 참여하였다. 598 | 599 | 섹스와 철학 600 | 《섹스와 철학》(Sex & Philosophy)은 타지키스탄에서 제작된 모흐센 마흐말바프 감독의 2005년 드라마 영화이다. 601 | 다레르 나자로브가 목소리를 맡았다. 602 | 이 영화의 배경은 타지키스탄이다. 603 | 2005년 9월 몬트리올 세계영화제에서 초연되었다. 604 | 대한민국, 터키, 이탈리아, 싱가포르, 러시아에서 극장 상영되었다. 605 | 606 | 도둑과 경관 607 | 《도둑과 경관》(Rene La Canne)은 프랑스에서 제작된 프란시스 지로드 감독의 1976년 영화이다. 608 | 장 카르메 등이 주연으로 출연하였고 자크-에릭 스트라우스 등이 제작에 참여하였다. 609 | 출시명은 누구에게 줄까요 610 | 이다. 611 | 1977년 개봉되었으며 534,714명의 관람객 수를 기록하였다. 612 | 613 | 언제까지나 그대만을 614 | 《언제까지나 그대만을》는 한국에서 제작된 권영순 감독의 1959년 영화이다. 615 | 이택균 등이 주연으로 출연하였고 고병두 등이 제작에 참여하였다. 616 | 617 | 엑시트 운즈 618 | 《엑시트 운즈》(Exit Wounds)는 미국에서 제작된 안드레이 바르코비악 감독의 2001년 미스터리, 액션, 스릴러 영화이다. 619 | 스티븐 시걸 등이 주연으로 출연하였고 조엘 실버 등이 제작에 참여하였다. 620 | 621 | 김치관 (친일파) 622 | 김치관(金致寬)은 남해3·1 독립운동 (南海三一獨立運動) 1919년 4월 2일- 1919년 4월 6일 당시 많은 군중들의 시위 위세에 놀라 이를 경찰 주재소에 밀고한 인물이다. 623 | 제2대 김치관(金致勸) 624 | 취임일 : 1916.07.20 625 | 이임일 : 1922.09.23 626 | 출생 시기 등 신상 정보는 알려진 바 없다. 627 | 일제 강점기때의 김치관(金致勸)은 남해군 제 2대 고현면장였다. 628 | 남해3·1 독립운동 (南海三一獨立運動) 1919년 4월 2일- 1919년 4월 6일 당시. 설천면 남양리에서 출발한 독립만세 시위 행렬이 문항리, 진목리, 비란리을 지나 고현면 도마리. 시위행렬이 고현면(古縣面) 이어리(당시 고현면 사무소 소재지는 이어리)에 이르자 그곳 고현 면장 김치관(金致寬)은 많은 군중들의 시위 위세에 놀라 이를 경찰 주재소에 밀고하였고, 629 | 파도와 같은 시위 군중의 힘을 이기지 못한 경찰은 결국 발포를 해 이를 진압하기 이른다. 630 | 이때 일본의 주구(走狗) 김치관(金致寬)은 경찰의 경비전화를 빌려 사천경찰서에 이곳 사태의 위급함을 알리면서 경찰과 일군을 출동시켜달 응원(應援)해라고 요청하였다. 631 | 632 | I Don't Care 633 | "I Don't Care"는 영국의 가수 에드 시런과 캐나다의 가수 저스틴 비버의 노래입니다. 634 | 635 | 눈부신 하루 636 | 눈부신 하루는 다음을 의미한다. 637 | 638 | 눈부신 하루 (2005년 영화) 639 | 《눈부신 하루》(One Shining Day)는 한국에서 제작된 민동현 감독의 2005년 드라마, 판타지, 멜로/로맨스 영화이다. 640 | 모리 유키에 등이 주연으로 출연하였고 차보현 등이 제작에 참여하였다. 641 | 642 | 써튼 퓨리 643 | 《써튼 퓨리》(Certain Fury)는 미국에서 제작된 스티븐 질렌홀 감독의 1985년 액션, 드라마 영화이다. 644 | 테이텀 오닐 등이 주연으로 출연하였고 길버트 아들러 등이 제작에 참여하였다. 645 | 646 | 프랜서 647 | 프랜서는 다음을 의미한다. 648 | 649 | 프랜서 (1989년 영화) 650 | 《프랜서》(Prancer)는 미국에서 제작된 존 D. 핸콕 감독의 1989년 드라마, 가족 영화이다. 651 | 샘 엘리어트 등이 주연으로 출연하였고 라파엘라 드 로렌티스 등이 제작에 참여하였다. 652 | 653 | 프랜서 (2001년 영화) 654 | 《프랜서》(Prancer Returns)는 캐나다에서 제작된 조슈아 버틀러 감독의 2001년 영화이다. 655 | 존 코베트 등이 주연으로 출연하였고 오스카 L. 코스토 등이 제작에 참여하였다. 656 | 657 | 드라큐라 애마 658 | 《드라큐라 애마》는 한국에서 제작된 석도원 감독의 1994년 드라마, 에로 영화이다. 659 | 오노아 등이 주연으로 출연하였고 정경희 등이 제작에 참여하였다. 660 | 661 | 사랑은 무서워 662 | 《사랑은 무서워》는 한국에서 제작된 김묵 감독의 1965년 영화이다. 663 | 강신성일 등이 주연으로 출연하였고 주동진 등이 제작에 참여하였다. 664 | 665 | 바늘풀족 666 | 바늘풀족(---族, )은 미나리아과의 족이다. 667 | 668 | 마리아스 러버 669 | 《마리아스 러버》(Maria's Lovers)는 미국에서 제작된 안드레이 콘찰로프스키 감독의 1984년 드라마, 멜로/로맨스 영화이다. 나스타샤 킨스키 등이 주연으로 출연하였고 로렌스 테일러-모토프 등이 제작에 참여하였다. 670 | 671 | 경상도 사나이 672 | 《경상도 사나이》는 한국에서 제작된 민경식 감독의 1960년 영화이다. 673 | 이대엽 등이 주연으로 출연하였고 박시춘 등이 제작에 참여하였다. 674 | 675 | Someone You Loved 676 | "Someone You Loved"는 스코틀랜드의 팝 록 밴드 루이스 카팔디의 노래이다. 677 | 678 | 왕자 미륵 679 | 《왕자 미륵》은 한국에서 제작된 이태환 감독의 1959년 영화이다. 680 | 방수일 등이 주연으로 출연하였고 성동호 등이 제작에 참여하였다. 681 | 682 | 퍼펙트 웨딩 683 | 《퍼펙트 웨딩》(Monster-In-Law)은 미국에서 제작된 로버트 루케틱 감독의 2005년 코미디, 멜로/로맨스 영화이다. 684 | 제니퍼 로페즈 등이 주연으로 출연하였고 폴라 웨인스타인 등이 제작에 참여하였다. 685 | 686 | 블랙 로브 687 | 《블랙 로브》(Black Robe)는 캐나다에서 제작된 브루스 베레스포드 감독의 1991년 드라마 영화이다. 688 | 로데어 블루토 등이 주연으로 출연하였고 수 밀리켄 등이 제작에 참여하였다. 689 | 690 | Liar (노래) 691 | "Liar"는 카밀라 카베요의 노래이다. 692 | 693 | 화야 694 | 《화야》는 한국에서 제작된 최영철 감독의 1983년 드라마 영화이다. 695 | 왕호 등이 주연으로 출연하였고 최춘지 등이 제작에 참여하였다. 696 | 697 | 힛쳐 (2007년 영화) 698 | 《힛쳐》(The Hitcher)는 미국에서 제작된 데이브 마이어스 감독의 2007년 공포, 액션, 범죄, 스릴러, 드라마 영화이다. 699 | 숀 빈 등이 주연으로 출연하였고 마이클 베이 등이 제작에 참여하였다. 700 | 701 | There's Nothing Holdin' Me Back 702 | "There's Nothing Holdin' Me Back"는 캐나다의 가수 숀 멘데스의 노래이다. 703 | 704 | 신풍협객 705 | 《신풍협객》은 한국에서 제작된 김시현 감독의 1972년 영화이다. 706 | 남일 등이 주연으로 출연하였고 박원석 등이 제작에 참여하였다. 707 | 708 | 바디 스내치 709 | 《바디 스내치》(Body To Body, Corps A Corps)는 프랑스에서 제작된 프랑소와 한스 감독의 2003년 스릴러, 드라마 영화이다. 710 | 엠마누엘 자이그너 등이 주연으로 출연하였다. 711 | 712 | 핵분열가족 713 | 《핵분열가족》(The Freaking Family)은 한국에서 제작된 박재영 감독의 2004년 코미디, 공포, 가족 영화이다. 714 | 이현정 등이 주연으로 출연하였다. 715 | 716 | 위험한 진실 717 | 《위험한 진실》(Truth Or Consequences, N.M.)은 미국에서 제작된 키퍼 서덜랜드 감독의 1997년 액션, 범죄, 드라마 영화이다. 718 | 빈센트 갈로 등이 주연으로 출연하였고 케빈 J. 메식 등이 제작에 참여하였다. 719 | 720 | 나의 친구여 721 | 《나의 친구여》는 한국에서 제작된 유장안 감독의 1928년 영화이다. 722 | 나웅 등이 주연으로 출연하였고 단천 등이 제작에 참여하였다. 723 | 724 | 퍼펙트 머더 725 | 《퍼펙트 머더》(A Perfect Murder)는 미국에서 제작된 앤드루 데이비스 감독의 1998년 범죄, 스릴러 영화이다. 726 | 마이클 더글라스 등이 주연으로 출연하였고 앤 코펠슨 등이 제작에 참여하였다. 727 | 728 | 서울 야누스 729 | 《서울 야누스》(Seoul Janus)는 한국에서 제작된 김영한 감독의 1991년 영화이다. 730 | 하재영 등이 주연으로 출연하였고 임상돈 등이 제작에 참여하였다. 731 | 732 | 로잔나 포에버 733 | 《로잔나 포에버》(Roseanna's Grave, Roseanna Forever)는 이탈리아에서 제작된 폴 웨이랜드 감독의 1997년 영화이다. 장 르노 등이 주연으로 출연하였고 폴 트리비츠 등이 제작에 참여하였다. 734 | 735 | 웰컴 프레지던트 736 | 《웰컴 프레지던트》(Welcome To Mooseport)는 미국에서 제작된 도날드 페트리 감독의 2004년 코미디 영화이다. 737 | 진 핵크만 등이 주연으로 출연하였고 마크 프리드맨 등이 제작에 참여하였다. 738 | 739 | 셀러리족 740 | 셀러리족(celery族, )은 미나리아과의 족이다. 741 | 742 | 지옥의 특전대 743 | 《지옥의 특전대》(The Wild Geese)는 영국에서 제작된 앤드류 V. 맥라글렌 감독의 1978년 전쟁, 액션 영화이다. 744 | 리차드 버튼 등이 주연으로 출연하였고 유언 로이드 등이 제작에 참여하였다. 745 | 746 | 버수스 747 | 버수스는 다음을 의미한다. 748 | 749 | 버수스 (2000년 영화) 750 | 《버수스》(Versus)는 미국에서 제작된 기타무라 류헤이 감독의 2000년 액션, 모험, 판타지 영화이다. 751 | 사카구치 타쿠 등이 주연으로 출연하였다. 752 | Reviews 753 | 754 | 7인의 새벽 755 | 《7인의 새벽》(Running Seven Dogs)은 한국에서 제작된 김주만 감독의 2001년 코미디, 액션 영화이다. 756 | 이지현 등이 주연으로 출연하였고 여한구 등이 제작에 참여하였다. 757 | 758 | 하이랜더 2 759 | 《하이랜더 2》(Highlander II: The Quickening)는 프랑스에서 제작된 러셀 멀케이 감독의 1991년 액션, SF 영화이다. 760 | 크리스토퍼 램버트 등이 주연으로 출연하였고 피터 S. 데이비스 등이 제작에 참여하였다. 761 | 762 | 헬레이저 3 763 | 《헬레이저 3》(Hellraiser III: Hell On Earth)는 미국에서 제작된 안소니 힉콕스 감독의 1992년 공포 영화이다. 764 | 케빈 번하드트 등이 주연으로 출연하였고 크리스토퍼 피그 등이 제작에 참여하였다. 765 | 766 | 센터 오브 월드 767 | 《센터 오브 월드》(The Center Of The World)는 미국에서 제작된 웨인 왕 감독의 2001년 드라마 영화이다. 768 | 몰리 파커 등이 주연으로 출연하였고 웨인 왕 등이 제작에 참여하였다. 769 | 770 | 캅 랜드 771 | 《캅 랜드》(Cop Land)는 미국에서 제작된 제임스 맨골드 감독의 1997년 네오 누아르 드라마 영화이다. 772 | 실베스터 스탤론 등이 주연으로 출연하였고 카리 우즈 등이 제작에 참여하였다. 773 | 774 | 엘 토포 775 | 《엘 토포》(The Gopher, El Topo)는 멕시코에서 제작된 알레한드로 조도로프스키 감독의 1970년 서부 영화이다. 776 | 알레한드로 조도로프스키 등이 주연으로 출연하였다. 777 | 778 | 햄버거 쟈니 779 | 《햄버거 쟈니》는 한국에서 제작된 설태호 감독의 1988년 드라마, 멜로/로맨스 영화이다. 780 | 자니 윤 등이 주연으로 출연하였고 설태호 등이 제작에 참여하였다. 781 | 782 | 스피룰라 783 | 스피룰라는 십완상목 두족류의 일종으로 몸속에 나선형의 껍데기를 가지고 있다. 784 | 2개의 지느러미 사이 약간 오목한 곳에 발광기관을 가지고 있으며 먹물주머니는 아주 작다. 785 | 스피룰라는 머리와 8개의 짧은 다리 그리고 2개의 촉완을 모두 외투강 안에 넣고 움츠리는 동작도 가능하다. 786 | 스피룰라를 제외하고 스피룰라목에 속하는 종들은 모두 멸종되었고 현존하는 종은 스피룰라 하나 뿐이다. 787 | 학명은 스피룰라 스피룰라("spirula spirula")이며 깊은 바다에 살고 올라오는 법이 잘 없어 한동안 스피룰라에 대해 알 수 있는 것이라고는 죽은 뒤 떠오르는 껍데기밖에는 없어 정체가 밝혀지지 않다가 최근 발견되어 그 정체가 세상에 알려졌다. 788 | 789 | 폰티 790 | 폰티는 다음 인물을 가리킨다. 791 | 792 | 마켄젠 793 | 마켄젠은 다음 인물을 의미한다. 794 | 795 | 셀리눔족 796 | 셀리눔족(selinum族, )은 미나리아과의 족이다. 797 | 798 | 송병기 799 | 송병기(宋炳琪, 1962년 3월 10일 ~ )는 대한민국의 교통, 토목 공학자이자, 공무원, 정치인이다. 800 | 801 | 체이스 앤더슨 802 | 로버트 체이스 앤더슨 (Robert Chase Anderson, 1987년 11월 30일 ~ )은 미국 프로야구 아메리칸 리그 토론토 블루제이스의 선수이다. 803 | 2009년 9라운드 276순위로 애리조나 다이아몬드백스에 입단 했다. 804 | 2014년 5월 11일 시카고 화이트삭스와의 경기에서 첫 메이저리그 데뷔를 하였다. 805 | 2016년 1월 30일 밀워키 브루어스의 진 세구라 등과 트레이드 되어 에런 힐과 함께 애리조나 다이아몬드백스에서 밀워키 브루어스로 이적했고, 2019년 11월 4일 트레이드를 통해 다시 토론토 블루제이스로 팀을 옮겼다. 806 | ※ 2019년 시즌 종료 기준 807 | 808 | 블란카 다라곤 왕녀 (1424년) 809 | 블란카 다라곤 왕녀()는 아라곤 왕국과 나바라 왕국의 왕녀이자 나바라 왕국의 대립 여왕 수리아 2세()였으며 카스티야 국왕 엔리케 4세가 아스투리아스 공 엔리케 시절의 부인(아스투리아스 공비)이다. 810 | 811 | 레드 플래닛 812 | 《레드 플래닛》(Red Planet)은 미국, 오스트레일리아에서 제작된 안토니 호프만 감독의 2000년 SF, 액션, 스릴러 영화이다. 813 | 발 킬머 등이 주연으로 출연하였고 브루스 버그만 등이 제작에 참여하였다. 814 | 815 | 조지 왕의 광기 816 | 《조지 왕의 광기》(The Madness Of King George)는 영국에서 제작된 니콜라스 하이트너 감독의 1994년 코미디, 드라마 영화이다. 817 | 나이젤 호손 등이 주연으로 출연하였고 스티븐 에반스 등이 제작에 참여하였다. 818 | 819 | 우연한 여행 820 | 《우연한 여행》은 한국에서 제작된 김정진 감독의 1994년 드라마 영화이다. 821 | 김명곤 등이 주연으로 출연하였고 유인택 등이 제작에 참여하였다. 822 | 823 | 심야의 탈출 824 | 심야의 탈출은 다음을 의미한다. 825 | 826 | 심야의 탈출 (1947년 영화) 827 | 《심야의 탈출》(Odd Man Out)은 영국에서 제작된 캐럴 리드 감독의 1947년 범죄, 스릴러, 드라마 영화이다. 828 | 제임스 메이슨 등이 주연으로 출연하였고 캐럴 리드 등이 제작에 참여하였다. 829 | 830 | 심야의 탈출 (1982년 영화) 831 | 《심야의 탈출》(Night Crossing)은 영국에서 제작된 델버트 맨 감독의 1981년 영화이다. 832 | 존 허트 등이 주연으로 출연하였고 톰 리취 등이 제작에 참여하였다. 833 | 834 | 돌아온 손오공 835 | 《돌아온 손오공 - 동훈별곡》은 한국에서 제작된 은희복 감독의 1990년 SF, 모험 영화이다. 836 | 이원승 등이 주연으로 출연하였고 문여송 등이 제작에 참여하였다. 837 | 838 | 에어 레이지 839 | 《에어 레이지》(Air Rage)는 미국에서 제작된 프레드 올렌 레이 감독의 2001년 액션 영화이다. 840 | 아이스-티 등이 주연으로 출연하였고 돈 키 주니어 등이 제작에 참여하였다. 841 | 842 | 미녀 사냥 843 | 《미녀 사냥》은 한국에서 제작된 김오대 감독의 1990년 드라마, 멜로/로맨스 영화이다. 844 | 이충식 등이 주연으로 출연하였고 김추련 등이 제작에 참여하였다. 845 | 846 | 크리스마스 건너뛰기 847 | 《크리스마스 건너뛰기》(Christmas With The Kranks)는 미국에서 제작된 조 로스 감독의 2004년 코미디, 드라마 영화이다. 848 | 팀 알렌 등이 주연으로 출연하였고 마이클 바네이단 등이 제작에 참여하였다. 849 | 850 | 스타힐리조트 851 | 스타힐리조트는 한국 경기도 남양주시 화도읍에 위치한 스키장이다. 852 | 과거 명칭인 천마산 스키장(또는 리조트)으로도 널리 알려져 있다. 853 | 854 | 최갑석 855 | 최갑석이라는 동명이인은 다음과 같다. 856 | 857 | 알프스 스키장 858 | 알프스 스키장 또는 알프스리조트는 한국 강원도 고성군 간성읍에 위치한 스키장이다. 859 | 현재는 휴장 상태로 재개장 여부는 알려지지 않았다. 860 | 861 | 낮과 밤 (드라마) 862 | 《낮과 밤》은 2020년 방송 예정 863 | 864 | 날아라 슛돌이 - 뉴 비기닝 865 | 《날아라 슛돌이 - 뉴 비기닝》은 KBS 2TV에서 방송되는 텔레비전 프로그램이다. 866 | 축구 초보에서부터 완성형 축구선수 등 다양한 실력을 가진 어린이들이 출연, 친구가 필요한 아이들이 축구를 통해 처음 만나 서로 부족했던 부분을 만회하면서, 성장 스토리를 그리는 스포츠 예능 프로그램 867 | 868 | 대명비발디파크 869 | 대명비발디파크는 한국 강원도 홍천군 서면에 위치한 스키장이다. 870 | 871 | 즈베즈다 (방송) 872 | 전러시아 국립 방송채널 "조국"()는 러시아의 국영 방송으로, 러시아 국방부가 소유하고 있다. 873 | 즈베즈다는 러시아어로 "조국"이라 하며, 현재 최고경영자는 그리고리 크리체프스키로, 과거 NTV에서 활동 한 적 있다. 874 | 1998년 러시아 국방부 부서인 러시아 국방부 중앙 텔레비전 및 라디오 스튜디오가 새로운 방송 설립을 위한 입찰에 성공하면서 개국 준비를 앞두고 있었으며, 2001년 9월에는 러시아 통신부에 의해 2주간 경고를 받은 적이 있었다. 875 | 876 | 오투리조트 877 | 오투리조트는 한국 강원도 태백시 황지동에 위치한 스키장이다. 878 | 879 | 나가오 야스노리 880 | 나가오 야스노리(, 1950년 5월 2일 ~ )는 일본의 전 프로 야구 선수이자 야구 지도자이다. 881 | 사가현 사가시 출신이며 현역 시절 포지션은 내야수였다. 882 | 사가니시 고등학교 시절에는 내야수, 대기 투수로서 활약했다. 883 | 2학년 때인 1967년 여름에는 3학년생이 졸업한 것에 의한 야구부원 부족으로 경기를 할 수 없게 되자 각 교실을 돌며 선수를 모았다는 일화가 있다. 884 | 3학년 때인 1968년 하계 고시엔 사가현 예선에서 준결승에 진출했지만 사가 공업고등학교에게서 9회에 역전패를 당해 고시엔 대회 출장은 이루질 못했다. 885 | 졸업 후에는 이스즈 자동차에 입사, 사내 야구부에서는 2번 타자로서 1971년 도시 대항 야구 대회에 출전했다. 886 | 팀내 에이스 도요타 겐지를 거느리고 2차전에 진출했지만 에 패하여 탈락했다. 887 | 그해 프로 야구 드래프트 회의에서 니시테쓰 라이온스로부터 3순위 지명을 받았지만 입단을 거부했고 이듬해 1972년 드래프트 1순위로 야쿠르트 아톰스에 입단했다. 888 | 프로 2년째인 1974년에는 도조 후미히로, 3년째인 1975년에는 마스카와 마이쿠와 유격수 자리를 놓고 경쟁했다. 889 | 1976년에는 2루수로 되돌아가면서 이듬해 1977년에는 주전으로 고정됐고 그 해는 처음으로 규정 타석(32위, 타율 0.244)을 채우는 등 3년 만의 A클래스 진입과 동시에 팀의 첫 2위 도약에 기여했다. 890 | 1978년에는 데이브 힐튼의 입단에 의해서 2루수 자리를 양보했지만 대기 내야수로서는 최초로 팀의 리그 우승에 기여했다. 891 | 그해 한큐 브레이브스와 맞붙은 일본 시리즈에서는 대타로서 2경기에 출전했고 10월 18일에 열린 4차전(니시노미야)에서는 0대 5 상황에서 상대 투수 이마이 유타로로부터 역전의 계기가 되는 안타를 때려내며 야쿠르트 구단 사상 첫 일본 시리즈 우승에 기여했다. 892 | 같은 해 오프에는 간베 도시오, 사토 다케히데, 데라다 요시타카와의 맞트레이드로 찰리 매뉴엘과 함께 긴테쓰 버펄로스로 이적했다. 893 | 긴테쓰에서도 내야 유틸리티 플레이어로 활약하며 1979년에는 규정 타석 미만이면서도 타율 0.310의 성적을 기록했고 긴테쓰에서 3년 동안 팀의 리그 2연패 달성에 공헌했다. 894 | 1982년 1월에는 현금 트레이드로 한신 타이거스에 이적했다. 895 | 그해 시즌 중인 5월 25일에 자택에서 화재가 발생하여 피해를 입었지만, 개인 최고 타율인 0.358을 기록한 것 외에도 주로 대타로 활약했다. 896 | 1985년에 트레이드로 한신에 입단한 나가사키 게이지와 함께 좌완 대타로 활약하면서 대타로서의 타율이 3할을 넘는 등 팀의 21년 만의 리그 우승과 동시에 일본 시리즈 우승에도 기여했다. 897 | 1987년을 끝으로 현역에서 은퇴했다. 898 | 이후 한신에서 2군 수비·주루 코치(1988년 ~ 1990년, 2010년), 2군 내야 수비·주루 코치(1994년 ~ 1995년), 2군 내야 수비 코치(1996년), 2군 육성 코치(2011년), 편성부 스카우트(1991년 ~ 1993년, 1997년 ~ 2009년) 등을 역임했다. 899 | 스카우트로 활동하던 시절에는 주로 규슈 지역을 담당하여 마토바 간이치, 기다 고, 노하라 마사시, 시라니타 히로카즈, 가이 유헤이 등을 영입했다. 900 | 2014년 12월부터 2017년까지 모교인 사가니시 고등학교에서 코치를 맡았고 2018년부터는 사가 현립 다라 고등학교 감독으로 맡고 있다. 901 | 902 | 한솔오크밸리 903 | 한솔오크밸리는 한국 강원도 원주시 지정면에 위치한 스키장이다. 904 | 905 | 양지파인리조트 906 | 양지파인리조트는 한국 경기도 용인시 처인구 양지면에 위치한 스키장이다. 907 | 지산포레스트리조트와 가깝다. 908 | 909 | 지산포레스트리조트 910 | 지산포레스트리조트는 한국 경기도 이천시 마장면에 위치한 스키장이다. 911 | 양지파인리조트와 가깝다. 912 | 913 | 곤지암리조트 914 | 곤지암리조트는 한국 경기도 광주시 도척면에 위치한 스키장이다. 915 | LG그룹에 의해 운영된다. 916 | 917 | 베어스타운 918 | 베어스타운은 한국 경기도 포천시 내촌면에 위치한 스키장이다. 919 | 2014년 이랜드그룹에 인수되었다. 920 | 921 | 에덴밸리리조트 922 | 에덴밸리리조트는 한국 경상남도 양산시 원동면에 위치한 스키장이다. 923 | 현재 한국 최남단의 스키장이다. 924 | 925 | 알렉스 폰티 926 | 알렉스 지오 폰티는 1953년 9월 1일 이탈리아 로마에서 태어났고 카를로 폰티의 장남이자 이탈리아 영화제작자이며 이탈리아 모델이다. 927 | 친할아버지인 레오네 폰티의 얼굴도 보지도 못하고 어린 시절에 이탈리아 건축가인 지오 폰티를 할아버지로 살아왔고 종조부인 줄리오 폰티, 종조모인 리사 폰티, 레티시아 폰티, 지오바나 폰티, 증조할아버지인 에토레 폰티는 이탈리아 정치인이고 새엄마인 소피아 로렌은 이탈리아 배우로 활동하고 누나인 구엔달리나 폰티는 변호사이며 아내인 산드라 몬텔레오니 대표는 이탈리아 기업인이고 딸인 안젤리카 폰티는 1982년생이라 이탈리아 모델이라고 살아왔다. 928 | 종조부인 안드레아 폰티와 지안펠리스 폰티의 이름을 보내고 있으며 현재는 영화기획자로 활동하고 있었다. 929 | 930 | 카를로스 곤 931 | 카를로스 곤(Carlos Ghosn, 1954년 3월 9일 ~ )은 브라질에서 태어난 레바논 혈동의 프랑스의 사업가이다. 932 | 레바논 혈통인 레바논-브라질 이중국적 아버지와 프랑스인 어머니 사이에서 출생해 삼중국적을 가지고 있다. 933 | 그랑제콜 준비반에 가기 위해 프랑스로 가서 우수한 그랑제콜을 졸업하고 르노에 입사했다. 934 | 르노-닛산 연합 이후 닛산의 개혁을 이끌었다. 935 | 일본에서 배임혐의를 받자 레바논으로 몰래 출국하였다. 936 | 937 | 무주동계올림픽 구상 938 | 이하는 과거 무주 동계올림픽의 유치 구상에 대하여 다룬다. 939 | 1992년 북한이 1995년 개최하기로 했던 제3회 동계아시아경기대회를 포기하였다. 940 | 이에 대회의 국내 유치 논의가 있었고 전라북도의 무주와 강원도의 용평(평창) 등이 후보지로 떠올랐다. 941 | 두 지역의 경쟁 끝에 결과적으로 전북은 1997년 제18회 동계유니버시아드대회를, 강원은 1999년 제4회 동계아시아경기대회를 유치하게 된다. 942 | 이후 두 대회는 각자의 목표인 동계올림픽을 위한 테스트이벤트의 성격을 띄게 되었다. 943 | 2000년대 들어 국가적으로 2010년 동계올림픽의 유치를 추진하며 전북(무주)은 강원(평창)과 다시 한번 경쟁하게 된다. 944 | 그 결과 국내 후보지로 선정된 평창은 공식 투표에서 캐나다의 밴쿠버에 패해 유치에 실패하였다. 945 | 이후 평창이 다시 2014년의 대회 유치를 추진하자 무주는 이전 선정 당시 2014년의 대회 후보지로 무주가 우선한다는 합의가 있었다며 반발하였다. 946 | 이와 비슷한 시기 태권도 공원의 장소가 무주로 결정되며 갈등이 일단락되었다. 947 | 한편 평창은 2014년과 2018년 대회 유치에 연이어 도전한 끝에 2018년 대회를 유치하게 된다. 948 | 2018년 동계올림픽을 앞두고 활강 종목 경기장이 들어설 가리왕산의 환경 문제가 부각되자 전북은 경기장의 신설 대신 무주리조트를 보완하여 활용하자고 주장하였다. 949 | 그러나 이는 실현되지 않았다. 950 | 951 | 인구집단건강 952 | 인구집단건강(人口集團健康, Population health)은 개인들의 모임인 인구집단의 건강과 인구집단 내에서의 건강의 분포를 의미한다. 953 | 954 | 건강영향평가 955 | 건강영향평가(Health Impact Assessment, HIA)는 정책, 계획, 프로그램 또는 프로젝트가 인구집단건강과 인구집단의 건강에 영향을 미치는 요인에 어떠한 영향을 끼치는지 판단하는 도구, 절차, 방법 또는 그 조합들을 의미한다. 956 | 957 | 스피룰라 스피룰라 958 | 스피룰라 스피룰라는 스피룰라목에 속하는 두족류 중 유일하게 현존하는 종이다. 959 | 스피룰라 스피룰라가 스피룰라목의 마지막 종이라고 할 수 있기 때문에 스피룰라 스피룰라가 멸종한다면 스피룰라목에도 더 이상 현존하는 종은 없게 되는 것이다. 960 | 또한 스피룰라 스피룰라(spirula spirula)는 학명이며 스피룰라라고 부르는 것이 보통이다. 961 | 962 | 미키 하지메 963 | 미키 하지메(, 1977년 4월 25일 ~ )는 일본의 전 프로 야구 선수이자 야구 지도자이며, 현재 퍼시픽 리그인 도호쿠 라쿠텐 골든이글스 감독이다. 964 | 오사카부 오사카시 스미노에구 출신이며 현역 시절 포지션은 내야수였다. 965 | 우에노미야 고등학교 시절에는 고교 통산 23홈런을 기록할 정도의 간판 타자로 알려지면서 1995년 프로 야구 드래프트 회의에서 후쿠도메 고스케(긴테쓰가 지명권 획득), 사와이 료스케(지바 롯데가 지명권 획득)와 제비뽑기에서 패한 야쿠르트 스왈로스로부터 1순위 지명(낙첨 1순위)을 받고 입단했다. 966 | 2001년에는 79경기에 출전했지만 시즌 타율이 2할을 넘지 못할 정도의 저조한 성적을 남겨서 수뇌진들로부터 평가를 얻지 못했다. 967 | 2002년 이후에는 시로이시 노리유키와 노구치 요시유키의 성장, 다나카 히로야스 등의 입단도 있어서 내야수의 대기 선수 자리조차도 굳히지 못하는 시즌이 계속되고 있었다. 968 | 2004년에는 타격 요령에 눈을 뜬 것을 기해 스위치히터로 전향했는데 그 해에는 26타수 7안타를 기록했고 이듬해 2005년에는 11타수 4안타를 기록하여 출전 기회는 적었지만 어느 정도의 결과를 남겼다. 969 | 2007년 10월 9일에는 대타로 현역 마지막 경기에 출전한 후루타 아쓰야 선수 겸임 감독의 대주자로 기용됐다. 970 | 2008년에는 가와시마 게이조, 하시모토 요시타카, 오시모토 다케히코와의 맞트레이드로 후지이 슈고, 사카모토 야타로 등과 함께 홋카이도 닛폰햄 파이터스에 이적했다. 971 | 그 해 6월 8일에 3타수 2안타 1볼넷, 2루타를 포함해 2타점을 기록하는 맹활약으로 프로 13년째에 처음으로 히어로 인터뷰의 주인공이 되는 경험을 했다. 972 | 같은 해 10월 23일에 현역에서 은퇴했다. 973 | 2009년에 닛폰햄의 2군 내야 수비 주루 코치로 부임했고 2012년에는 1군 내야 수비 코치로 승격됐다. 974 | 이듬해 2013년 10월 14일에 닛폰햄을 퇴단했다. 975 | 2013년 10월 23일에 2014년 시즌부터 도쿄 야쿠르트 스왈로스 2군 내야 수비 주루 코치로 부임했다는 사실이 언론에 발표됐다. 976 | 이듬해 2015년에는 1군 작전 겸 내야 수비 주루 코치로 승격됐고 그 다음해인 2016년에는 1군 수석 코치 겸 내야 수비 주루 코치로 승격됐다. 977 | 2017년에는 1군 수석 코치로 부임했고 2018년에는 2군 수석 코치로 배치 전환됐다. 978 | 2019년에는 도호쿠 라쿠텐 골든이글스 2군 감독을 맡았고 같은 해 10월 11일에는 구단이 2020년부터 1군 감독을 맡게됐다는 내용의 보도 자료를 발표했다. 979 | 또한 현역 시절에 59안타를 기록하여 1군 감독으로 부임한 사례는 전임 라쿠텐 감독인 히라이시 요스케의 39안타, 전 한큐 브레이브스, 닛폰햄 파이터스 감독인 우에다 도시하루의 56안타에 이은 최소 기록이다. 980 | 잦은 손목 부상으로 인해 타격이 늘지 않았고 타격에 관해서는 신인 시절에 기대를 걸었던 만큼의 눈에 띈 성적을 남기지 못했다. 981 | 원래는 우타자였지만 빠른 발을 가졌다는 평가를 받아 양타자로 전향했다는 에피소드가 있다. 982 | 타격과는 대조적으로 빠른 발로 단순한 단거리 달리기 능력은 10대 시절에 절정을 이뤘다고 본인이 《슈칸 베이스볼》과의 인터뷰에서 말했으며 그 쇠약함을 말년에는 주루·도루 기술 향상으로 보강했다고 말한 바있다. 983 | 그런 반면 뜬공으로 따라나가는 등의 실수도 다소 많이 보였다. 984 | 수비 범위는 넓었지만 리스트에 문제가 있었기 때문에 송구에 대한 신뢰도는 그리 높지 않았다. 985 | 특히 2루에서의 실책이 가장 많았다. 986 | 987 | 벨렘나이트 988 | 벨렘나이트(Belemnitida, belemnites)는 중생대에 서식했던 두족류로 오징어의 직계 조상이라고 할 수 있다. 989 | 오징어의 직계 조상인 만큼 오징어와 판박이인데 지느러미가 있고 심지어는 먹물주머니까지 갖추고 있었다! 990 | 다만 오징어와는 달리 사냥에 특화된 촉완이 없고 6개의 다리에는 빨판 대신 가시가 나 있었다. 991 | 화살촉처럼 생긴 2cm 정도의 껍데기(화석 부분)는 몸속 가장 끝부분에 위치해 있었으며 암모나이트와 동시대에 살았던 두족류이다 992 | 보니 같은 두족류인 암모나이트와 함께 설명되는 경우가 많다. 993 | 994 | 크리스 워들 995 | 축구 기자 루크 기넬(Luke Ginnell)은 '매직 크리스(Magic Chris)'라는 별명을 썼으며, 워들은 "유럽에서 가장 좋은 공격형 미드필더 중 한 명으로 널리 인정받았다"고 썼다. 996 | 1978년부터 1998년까지 이어진 프로 경력에서, 그는 뉴캐슬 유나이티드, 토트넘 홋스퍼, 올랭피크 드 마르세유, 셰필드 웬즈데이 등을 포함한 여러 클럽에서 활동했다. 997 | 1989년, 450만 파운드의 이적료로 토트넘에서 마르세유로 이적하면서 그는 세계에서 세 번째로 비싼 선수가 되었으며, 클럽과 함께 3회 연속으로 리그 1 우승을 하고 1991년 유러피언 컵 결승전 에서 뛰었다. 998 | 웬즈데이에서 활동할 때는 1992-93 시즌에 보여준 활약상을 통해 잉글랜드축구기자협회(FWA) 올해의 축구선수로 선정되었다. 999 | 워들은 1985년에서 1991 년까지 잉글랜드 축구 국가대표팀에서 62경기에 출전했으며, 1986년 FIFA 월드컵 준준결승, 1990년 FIFA 월드컵 준결승 진출을 함께 했다. 1000 | 또한 UEFA 유로 1988에 출전하기도 했다. 1001 | 그는 50대의 나이에도 세미프로페셔널 수준의 노던 카운티즈 이스트 리그의 할람 소속으로 경기를 뛰기도 했으며 프리미어리그와 UEFA 챔피언스리그 팀원으로 BBC 라디오 5 라이브와 계약을 맺고 있다. 1002 | 워들은 펠로 주니어스와 함께 축구 경력을 시작하여 화이트하우스 SC, 마운트 플레전트 SC, HMH 프린팅, 펠로 SC, 림 레인 SC 및 클라크 채프먼에서 활동했으며 1978-79 시즌이 시작되기 전에 토 로 타운에 입단했다. 1003 | 워들은 식품 가공업(조미료 공장)에 종사하면서 선덜랜드와 코번트리 시티와의 입단 테스트에서 탈락했다. 1004 | 그는 1980년 7월 뉴캐슬 유나이티드에 1,000 파운드의 금액으로 입단했다. 1005 | 그는 1980년 10월 22일에 있었던 슈루즈베리 타운과의 홈 경기(1-0 승리)에서 2부 데뷔전을 치렀으며, 유력한 공격형 미드필더로 빠르게 정착하였고, 1983-84 시즌 말미에는케빈 키건, 피터 비어슬리와 함께 뉴캐슬의 1부 승격을 이끌었다. 1006 | 워들은 1984년 9월 22일에 로프터스 로드에서 있었던 퀸스 파크 레인저스와의 경기에서 전반전에만 해트트릭을 하며 4-0의 우위를 가져왔다. 1007 | 그러나, QPR의 반격으로 경기는 5-5로 끝났다. 1008 | 그는 25세의 나이임에도, 잉글랜드 U-21에 발탁되었고 1985년 3월에 있었던 아일랜드와의 경기에서 데뷔했다. 1009 | 워들은 뉴캐슬에서 170경기 46득점의 기록을 남긴 후, 1985년 7월 1일 59만 파운드의 이적료를 통해토트넘 홋스퍼에 입단했다. 1010 | 그는 리그 개막일에 벌어진 왓퍼드와의 홈 경기(4-0 승)에서 리그 데뷔전을 치르며 두 개의 득점을 기록했지만, 3위로 마친 이전 시즌과는 달리 10위로 시즌을 마감하면서, 피터 슈리브스가 감독에서 해임되고 루턴 타운에서 온 데이비드 플릿이 그의 후임자로 임명됐다. 1011 | 토트넘에 입단한 후, 잉글랜드 대표팀에서 정기적으로 활동하게 됐고 멕시코에서 있었던 1986년 FIFA 월드컵에서 8강에 진출한 팀에서 비어슬리와 다시 연이 닿았다. 1012 | 그는 월드컵 이후 가장 유익한 시즌을 보냈다. 1013 | 그는 1987년 코번트리가 스퍼스를 물리쳤던 FA컵에서 준우승 메달을 획득했고 리그에서는 3위로 마감했으며 리그 컵에서는 준결승에 올랐다. 1014 | 같은 해, 워들은 팝 차트에 이름이 올라가기도 했으며, 스퍼스와 잉글랜드 대표팀 동료인 글렌 호들과의 듀엣으로 제작한 싱글 'Diamond Lights'가 UK Top 20을 만들었습니다. 1015 | 1988년에는 유럽 선수권 대회에서 조별 리그 세 경기를 모두 패배한 잉글랜드 대표팀의 일원으로 있었다. 1016 | 1985년 헤이젤 참사의 영향으로 잉글랜드의 클럽의 유럽 대항전 출전이 금지되면서 워들이 해외 팀으로 이적할 것이라는 이야기가 있었지만, 해외로 이적하기 전까지 네 시즌을 화이트 하트 레인에서 보냈다. 1017 | 1989년 7월 1일, 토트넘에서 138경기 33득점의 기록을 남긴 워들은 450만 파운드의 이적료를 통해 프랑스의 클럽 올랭피크 드 마르세유로 이적했고 이는 당시 축구선수의 영입을 위해 지불된 금액 중 세 번째로 높은 금액이었다. 1018 | 프랑스에 있는 동안 클럽은 리그 1 우승 3회(1990, 1991, 1992)의 업적을 일궈냈다. 1019 | 또한 마르세유는 1991년 유러피언컵 결승전에서 츠르베나 즈베즈다와의 경기에서 패배하고 준우승에 그쳤다. 1020 | 1991-92 시즌에는 레인저스에서 이적해서 한 시즌을 보내고 다시 스코틀랜드로 돌아간 잉글랜드의 미드필더 트레버 스티븐과 함께 뛰기도 했다. 1021 | 워들은 1990년 FIFA 월드컵 준결승에서 잉글랜드 소속으로 6경기에 선발 출전했다. 1022 | 그는 서독과의 준결승에서 팀이 1-1로 비긴 경기의 연장전에서 포스트를 강타했다. 1023 | 그러나 이 경기에 대한 그의 마지막 기여는 승부차기에서 실축한 것이었고, 볼은 바를 맞고 나갔으며 독일을 결승에 보내버린 것이었다. 1024 | 그는 이후 토너먼트 이전에 유리 겔러와 마이클 잭슨과의 우연한 만남을 승부차기 실축의 책임으로 돌렸다. 1025 | 워들에 대한 겔러의 고별사는 "당신이 더 높이 갈수록, 더 강하게 떨어진다"였다고 보도됐다. 1026 | 그는 잉글랜드가 이탈리아에게 2-1로 패배한 3위 결정전에서 후보로 경기를 시작했다. 1027 | 마르세유에서 있었던 몇 년 동안, 팬들은 그에게 '매직 크리스(Magic Chris)'라는 별명을 붙여줬다. 1028 | 그는 전 마르세유 선수였던 로예르 마그누손의 후계자로 알려지고 있다. 1029 | 1998년에는 클럽의 100주년을 기념하여 진행된 올랭피크 드 마르세유 역대 최고의 선수 선정 투표에서 장피에르 파팽에 이어 2위에 오르기도 했다. 1030 | 그는 클럽에서 팝 뮤직 경력을 다시 이어갔고 팀 동료인 바질 볼리와 함께 "We've Got a Feeling" 이라는 노래를 녹음했다. 1990년에 있었던 잉글랜드의 승부차기 패배 이후 1년 만에, 워들과 마르세유는 1991년 유러피언 컵 결승전에 진출했다. 워들은 승부차기에서 나서지는 않았고 경기를 정규 시간을 0-0으로 끝낸 후 승부차기에서 다시 패배했다. 마르세유가 1993년에 유러피언 컵에서 우승했을 때는 워들이 이미 클럽을 떠난 상황이었다. 1031 | 워들은 1992년 7월에 100만 파운드의 이적료를 통해 셰필드 웬즈데이로 이적하면서 잉글랜드로 돌아왔고, 트레버 프랜시스의 지도를 받았다. 1032 | 이 클럽은 1992-93 시즌에 두 개의 국내 컵 대회 결승에 진출했으며(모두 아스널에게 패배했고 워들은 FA컵 결승전 재경기에서 웬즈데이의 득점을 기록했다), 1033 | 워들은 1993년에 축구기자협회 올해의 축구 선수로 선정되었다. 1034 | 1993-94 시즌에는 웬즈데이의 리그 컵 준결승 진출을 도왔지만, 이 우승 트로피를 향한 마지막 도전은 맨체스터 유나이티드에 의해 좌절되었고, 웬즈데이는 그 다음 두 시즌을 중하위권으로 마쳤으며, 1995년에는 프랜시스가 해임되고 워들과 함께 했었던 전직 토트넘 감독 데이비드 플릿이 이어받았다. 1035 | 이러한 활약에도 그는 1990년 7월 보비 롭슨의 뒤를 이어받은 그레엄 테일러 감독 하에서 단 3경기의 A매치에 출전했다. 1036 | 1996년 1월, 케빈 키건은 징계를 받은 다비드 지놀라의 대체를 위해 뉴캐슬 유나이티드에 워들을 재영입하려고 했지만, 10년도 더 이전에 뉴캐슬 팀에서 그와 함께 뛴 선수의 재영입에 대한 키건의 50만 파운드 제의는 거절됐고 키건은 데이비드 플릿이 이 35세의 선수에게 붙인 1백만 파운드의 가격을 지불하고 싶지 않았다. 1037 | 이 시기에 셀틱, 리즈 유나이티드, 선덜랜드 역시 워들과의 계약에 관심이 있었지만, 이적이 성사되지는 않았다. 1038 | 또한 번리가 그를 선수 겸 감독으로 선임하는 데 관심을 드러냈지만 워들은 힐즈버러에서 시즌을 마쳤다. 1039 | 109경기에 출전해서 10개의 득점과 그보다 더 많은 도움을 기록한 그의 힐즈버러에서의 마지막 경력은 부상으로 인해 망쳐졌고 1996-97 시즌에는 5경기를 뛰고 방출되었다 1040 | (올즈는 프리미어십의 상위권에 위치했었던 상황이었고, 젊은 감각 촬영 한 때 그는 1996-97 시즌에 5 개 게임을 출시 된 리치 험프리 - 5 경기에서 4 골을 - 그의 날개 아래) 후 데이비드 플리트 (David Pleat)가 109 경기를 뛰면서 더 많은 어시스트로 10 골을 넣었다. 1041 | 1996년 9월, 그는 스코틀랜드 퍼스트 디비전의 폴커크에 입단했지만, 그 다음달에 디비전 원의 브래드퍼드 시티에서 뛰기 위해 국경의 남쪽으로 돌아왔다. 1042 | 짧았지만 시티에서의 시간은 성공적이었고 그는 팬들의 확실한 지지를 받았다. 1043 | 그는 TV로 생중계된 허더즈필드 타운과의 경기의 코너킥 상황에서 직접 득점을 넣기도 했다. 1044 | 또한, 그가 구디슨 파크에서 있었던 에버턴과의 FA컵 경기(3-2 승)에서 넣은 골은 1997년 2 월 '매치 오브 더 데이 이달의 골(Match of the Day Goal of the Month)'에서 2위를 차지했다. 1045 | 브래드퍼드와 함께한 그의 노력은 시즌을 완전히 마치지 못했지만 디비전 원에서의 잔류에 기여했다. 1046 | 1997 년 3월, 7만 5천 파운드의 이적료를 통해 어렸을 때 응원했던 선덜랜드로 이적했고 에버튼을 상대로 하나의 득점을 올리고 선덜랜드의 득점에 도움을 줬지만 시즌이 끝날 때 선덜랜드가 프리미어리그에서 강등되는 것을 막지 못했다. 1047 | 1997년 5월, 그는 자유 이적으로 로커 파크로 적을 옮겼고 번리의 선수 겸 감독으로 선임됐다. 1048 | 번리는 실망스러운 시즌을 보냈고, 시즌이 끝날 때 강등을 면했을 뿐이었다. 1049 | 그는 1997년 10월에 있었던 본머스와의 경기(2-2 무)에서 하나의 득점을 기록했다. 1050 | 워들은 여름에 번리를 떠났고 1998년 9월에 토키 유나이티드에 입단했다. 1051 | 그는 수요일 토필드에서 7 번 뛰었고 코치로 수요일 셰필드로 돌아왔다. 1052 | 그는 1999 년 7 월 예비 팀 코치로 임명되어 지역 선술집에서 뛰었지만 2000 년 6 월 폴 주얼 (Paul Jewell) 을 감독으로 임명했다. 1053 | 토키 유나이티드에서 출발 한 후, Waddle는 비리 그 워크 Town 타운 에서 60 번의 출전과 3 골을 기록하면서 2 계절을 즐겼습니다. 1054 | 그의 가장 두드러진 모습은 Frickley Athletic과의 12–0 노던 프리미어 리그 기록에서 승리 한 것입니다. 1055 | 그는 또한 북부 프리미어 리그 퍼스트 디비전의 Glapwell 과 Stocksbridge Park Steels 에 출연하여 비 리그 수준에서 40 대 초반까지 경력을 계속했습니다. 1056 | 아마추어 수준에서 연주 한 셰필드 2012-13 시즌 동안 할람에 대한 Wragg 이상-40 리그 그는 무릎 부상으로 11 년 후 은퇴 와서 위해 서명 셰필드 기반의 비 리그 측 경이 2013년 7월 22일에. 그는 프리 시즌에 체스터 필드에 대한 데뷔를했다. 1057 | 하프 타임에 교체 선수로 등장했다. 1058 | 한림 FC는 6-2로 패했다. 1059 | Waddle은 2013 년 8 월 1 일에 1 년 계약을 체결하여 2013-14 시즌 프로모션 추진을 위해 ESPN 해설 팀의 일원으로 남아있는 한남을 약속했습니다. 1060 | 1985 년 3 월 26 일, 여전히 뉴캐슬 선수였던 Waddle은 Bobby Robson 의 잉글랜드에 의해 2-1로 승리하여 아일랜드 공화국 에서 처음으로 선임되었습니다. 1061 | 그는 곧 잉글랜드 대표팀의 정규 멤버가되었으며 그해 10 월 16 일 터키 에서 5-0으로이긴 10 번째 국제 경기에서 잉글랜드의 첫 골을 기록했다. 1062 | Waddle은 1986 년 과 1990 년 FIFA 월드컵 및 UEFA 유로 1988 에서 잉글랜드 대표팀에있었습니다. 1063 | 잉글랜드는 3 경기를 모두 잃은 유로 88의 그룹 스테이지에서 탈락했지만 1986 년 월드컵 준준결승과 1990 년 준결승에 도달했다. 1064 | 총격전에서 바 위로 1 인치는 서독으로 패배. 그는 잉글랜드가 진행될 경우 다음 경기에서 경기를 중단 한 Paul Gascoigne 이 너무 화가 나서 5 차 페널티를 받았다고 말했다. 1065 | 1990 년 월드컵에서의 Waddle의 공연은 2010 년 "The Guardian" 을 위해 썼던 Rob Bagchi에 의해 "최고"로 묘사되었습니다. 1066 | 그는 1991 년 10 월 16 일 터키에서 1-0으로 승리하면서 62 번의 캡을 마지막으로 우승했다. 1067 | 1989 년 5 월 27 일 스코틀랜드 와의 마지막 경기에서 잉글랜드는 6 골을 기록했다. 1068 | 1994 년 초 Terry Venables 가 새로운 잉글랜드 감독이되었을 때, 덴마크 와의 첫 경기에서 Waddle을 분대에 포함 시키려고 애썼다. 1069 | 그러나 Waddle은 당시 부상을 입었고 선택할 수 없었습니다. 1070 | 1997-98 시즌을 감독으로 보냈음에도 불구하고 Waddle은 은퇴 후 코칭으로 돌아 오지 않았으며 TV 축구 전문가, 논평자 및 스포츠 신문 작가가되었습니다. 1071 | 그는 이전에 Setanta Sports 및 ESPN 에서 근무했으며 현재 BBC Radio Five Live 의 프리미어 리그 축구 커버리지 분석가로 일하고 있습니다. 1072 | Waddle은 BBC Radio Five Live 에 프리미어 리그 경기의 요약으로 출연했으며 "The Sun" 신문에도 기사를 썼습니다. 1073 | Waddle은 Setanta Sports 와 2008-09 년 잉글랜드의 모든 시합에 대해 논평하기 위해 계약을 체결했습니다. 1074 | Waddle은 ESPN 의 잉글리쉬 프리미어 리그 축구 커버리지에 대한 공동 의견을 제출했으며 아랍 에미리트 두바이의 스튜디오에서 잉글리쉬 프리미어 리그를 커버하는 Showsports Arabia의 전문가입니다. 1075 | 2003 년 티에리 앙리 (Thierry Henry) 는 꿈의 팀 라인업에서 Waddle을 지명했습니다. 1076 |   에 잉글랜드 로의 무거운 패배 독일 의 두 번째 라운드에서 2010 FIFA 월드컵, 뒤뚱는 비판 영어 축구 협회는 주장 :는 "FA는 자신의 뒷부분에 앉아서 대회 이후 대회 후 아무것도 토너먼트을한다. 왜 듣지 않습니까? 왜 그들은 다른 나라를보고 '어떻게 인재를 계속 생산합니까?'라고 묻지 않습니까? 우리는 선수들로부터 재능을 코치합니다. . . 우리는 많은 아이디어가 부족하고 너무 실망입니다. 우리 리그의 돈은 무섭고 우리가하는 일은 쓰레기 아이디어로 낭비하는 것입니다. . . 우리는 템포를 유지하면 기회가 있다고 생각합니다. 우리는 한 방향으로 만 놀 수 있으며 가난합니다. 당신은 축구를 계속하고 시간당 백 마일을 뛰고 90 분 동안 팀을 압박하는 트로피를 얻기를 기대할 수 없습니다. 당신은 느리게, 느리게, 빨리 재생할 수 있어야하고 우리는 그것을 할 수 없습니다. " 1077 | Waddle에는 딸 Brooke과 아들 Jack이 있습니다. 1078 | 2012 년 4 월 29 일 Jack은 Chesterfield 에서 1 년 간의 첫 팀 계약을 체결했습니다. 1079 | 그의 사촌 인 앨런 와들 (Alan Waddle )은 핼리팩스 타운, 리버풀, 레스터 시티, 스완 지 시티, 뉴 포트 카운티, 맨스필드 타운, 하 틀풀 유나이티드 및 피터 버러 유나이티드 에서 리그 풋볼을 했습니다 . 1080 | 2005 년, 그는 셰필드의 Dore 에있는 한 술집 에서 한 남자를 공격 한 혐의로 기소되었습니다. 1081 | 그러나 증거 부족으로 기소됐다. 1082 | Waddle은 BBC 코미디 "The Fast Show" 에서 사용 된 대중 문화 참고 자료 풀의 핵심 부분이었습니다. 1083 | Waddle에 대한 언급과 사진은 쇼의 "Chanel 9"뉴스 세그먼트에서 정기적으로 등장했습니다. 1084 | 올랭피크 드 마르세유 1085 | 잉글랜드 1086 | 개인 1087 | 1088 | 유갈 1089 | 유갈(劉揭, ? ~ 기원전 166년)은 전한 전기의 관료이다. 1090 | 고제 때 낭(郞)이 되었다. 1091 | 고후 8년(기원전 180년), 고후가 죽고 동생 주허후 유장과 함께 여씨 타도를 모의한 제애왕이 거병하였다. 1092 | 중앙군을 쥐고 있었던 여산과 여록은 진압에 나서려 하였으나, 주발·진평의 사주를 받은 역기의 설득으로 봉국으로 돌아가려 하였다. 1093 | 그러나 가수의 간언을 들은 여산이 돌아가지 않고 입궁하려 하였다. 1094 | 전객 유갈은 주발의 명으로 황명을 사칭하여 역기와 함께 여록을 재차 설득하였고, 결국 여록은 북군(北軍)을 주발에게 넘기고 정말로 봉국으로 돌아갔다. 1095 | 여록이 돌아가자 유갈은 궁문을 닫고 여산이 들어오지 못하게 하였다. 1096 | 곧 대신들이 궁궐을 장악하였고, 여산은 유장에게 살해당하였다. 1097 | 여산을 죽인 대신들은 여씨 일족을 잡아들여 주멸하였고, 대왕 유항을 불러들여 황제로 옹립하였다 1098 | (문제). 유갈은 이때의 공으로 양신후(陽信侯)에 봉해지고 금 천 근을 받았다. 1099 | 양신이후 14년(기원전 166년)에 죽어 시호를 이(夷)라 하였다. 1100 | 아들 유중의(劉中意)가 작위를 이었으나, 경제 6년(기원전 151년) 죄를 지어 작위가 박탈되었다. 1101 | 1102 | 배가본드 2 1103 | 《배가본드 2》는 시즌 1을 시청했던 수많은 시청자들의 계속적인 요구에 따라, 편성이 확정된 드라마로서, 시청자들에게 또 하나의 전환점을 제공한 액션멜로 드라마다. 1104 | 차달건의 사막 이후의 다음 이야기로 전개 될것을 예상한다 1105 | 1106 | 모클렌어 1107 | 모클렌어(Moklen)는 태국 남부 서해안에서 쓰이는 오스트로네시아어족 언어이다. 1108 | 태국 남부와 미얀마에 분포하는 모켄어와 매우 가까운 관계이며 함께 모클렌어군을 이룬다. 1109 | Larish (2005)는 태국 내에서 모클렌어가 쓰이는 주요 지역을 3곳으로 나눈다. 1110 | 모클렌어는 주로 팡응아주에서 쓰이지만 라농주와 푸껫섬에서도 쓰인다. 1111 | Swastham (1982)은 태국 남부 팡응아주 타이므앙군 람피 마을()의 모클렌어 방언을 기술하였다. 1112 | Swastham (1982)은 람피 마을 주변의 모클렌어 사용 마을을 다음과 같이 북쪽에서 남쪽 순으로 나열한다. 1113 | 방삭(Bang Sak), 쿡칵(Khuk Khak), 방니앙(Bang Niang), 퉁마프라우(Thung Maphraw), 타찻차이(Tha Chat Chai). 1114 | Bishop & Peterson (1987)은 다양한 모클렌어 방언을 조사하였다. 1115 | 1116 | 총참모장 1117 | 총참모장은 군대에서 참모의 수장을 가리킨다. -------------------------------------------------------------------------------- /images/explicit-sparse-attention.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nawnoes/pytorch-gpt-x/6d6d8b3ef3c66a5f454e4a722fdbc26268312b89/images/explicit-sparse-attention.png -------------------------------------------------------------------------------- /images/macaron.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nawnoes/pytorch-gpt-x/6d6d8b3ef3c66a5f454e4a722fdbc26268312b89/images/macaron.png -------------------------------------------------------------------------------- /images/residual_attn.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nawnoes/pytorch-gpt-x/6d6d8b3ef3c66a5f454e4a722fdbc26268312b89/images/residual_attn.png -------------------------------------------------------------------------------- /images/rezero.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nawnoes/pytorch-gpt-x/6d6d8b3ef3c66a5f454e4a722fdbc26268312b89/images/rezero.png -------------------------------------------------------------------------------- /model/o_transformer.py: -------------------------------------------------------------------------------- 1 | import math 2 | import torch 3 | from torch.optim import Adam 4 | import torch.nn as nn 5 | import torch.nn.functional as F 6 | from torch.nn import CrossEntropyLoss 7 | import pytorch_lightning as pl 8 | from transformers import AdamW 9 | from deepspeed.ops.adam import DeepSpeedCPUAdam, FusedAdam 10 | from collections import OrderedDict 11 | 12 | 13 | def self_attention(query, key, value, mask=None, causal=False, explicit_topk=None, prev_attn=None): 14 | key_transpose = torch.transpose(key,-2,-1) # (bath, head_num, d_k, token_) 15 | matmul_result = torch.matmul(query,key_transpose) # MatMul(Q,K) 16 | d_k = query.size()[-1] 17 | attention_score = matmul_result/math.sqrt(d_k) # Scale 18 | 19 | pre_softmax_attn = None 20 | if prev_attn: 21 | attention_score = attention_score + prev_attn 22 | pre_softmax_attn = attention_score 23 | 24 | if mask is not None: 25 | attention_score = attention_score.masked_fill(mask == 0, -1e4) 26 | 27 | # is Decoder 28 | if causal: 29 | query_len = query.size()[2] 30 | # causal_mask = torch.tril(torch.ones(query_len, query_len)) 31 | # attention_score = attention_score.masked_fill_(causal_mask == 0, -1e4) 32 | i, j = torch.triu_indices(query_len, query_len, 1) 33 | attention_score[:, :, i, j] = -1e4 34 | 35 | # Explicit Sparse Transformer 36 | if explicit_topk and explicit_topk< attention_score.shape[-1]: 37 | top, _ = attention_score.topk(explicit_topk, dim=-1) # return value, indices 38 | vk = top[...,-1].unsqueeze(-1).expand_as(attention_score) 39 | mask = attention_score < vk 40 | attention_score.masked_fill_(mask,-1e4) 41 | del mask 42 | 43 | softmax_attention_score = F.softmax(attention_score,dim=-1) # 어텐션 값 44 | result = torch.matmul(softmax_attention_score,value) 45 | 46 | return result, softmax_attention_score, pre_softmax_attn 47 | 48 | class MultiHeadAttention(nn.Module): 49 | def __init__(self, head_num =8 , d_model = 512,dropout = 0.1, causal=False, explicit_sparse_attn_topk=None, residual_attn=False): 50 | super(MultiHeadAttention,self).__init__() 51 | 52 | # print(d_model % head_num) 53 | # assert d_model % head_num != 0 # d_model % head_num == 0 이 아닌경우 에러메세지 발생 54 | 55 | self.head_num = head_num 56 | self.d_model = d_model 57 | self.d_k = self.d_v = d_model // head_num 58 | self.causal = causal 59 | self.explicit_topk = explicit_sparse_attn_topk 60 | self.residual_attn = residual_attn # Residual Attention 61 | 62 | self.w_q = nn.Linear(d_model,d_model) 63 | self.w_k = nn.Linear(d_model,d_model) 64 | self.w_v = nn.Linear(d_model,d_model) 65 | self.w_o = nn.Linear(d_model,d_model) 66 | 67 | self.self_attention = self_attention 68 | self.dropout = nn.Dropout(p=dropout) 69 | 70 | def forward(self, query, key, value, mask = None, prev_attn=None): 71 | if mask is not None: 72 | # Same mask applied to all h heads. 73 | mask = mask.unsqueeze(1) 74 | 75 | batche_num = query.size(0) 76 | 77 | query = self.w_q(query).view(batche_num, -1, self.head_num, self.d_k).transpose(1, 2) 78 | key = self.w_k(key).view(batche_num, -1, self.head_num, self.d_k).transpose(1, 2) 79 | value = self.w_v(value).view(batche_num, -1, self.head_num, self.d_k).transpose(1, 2) 80 | 81 | attention_result, attention_score, pre_softmax_attn = self.self_attention(query, key, value, mask, self.causal, self.explicit_topk, prev_attn) 82 | attention_result = attention_result.transpose(1,2).contiguous().view(batche_num, -1, self.head_num * self.d_k) 83 | attn_output = self.w_o(attention_result) 84 | 85 | return attn_output, pre_softmax_attn 86 | 87 | class Scale(nn.Module): 88 | def __init__(self, scale_value, fn): 89 | super().__init__() 90 | self.scale_value = scale_value 91 | self.fn = fn 92 | def forward(self, input): 93 | x = self.fn(input) 94 | return x * self.scale_value 95 | 96 | 97 | class FeedForward(nn.Module): 98 | def __init__(self,d_model, dropout = 0.1, activation='gelu'): 99 | super(FeedForward,self).__init__() 100 | self.w_1 = nn.Linear(d_model, d_model*4) 101 | self.w_2 = nn.Linear(d_model*4, d_model) 102 | self.dropout = nn.Dropout(p=dropout) 103 | 104 | if activation =='gelu': 105 | self.activation = F.gelu 106 | elif activation == 'relu': 107 | self.activation = F.relu 108 | 109 | def forward(self, x): 110 | return self.w_2(self.dropout(self.activation(self.w_1(x)))) 111 | 112 | class LayerNorm(nn.Module): 113 | def __init__(self, features, eps=1e-6): 114 | super(LayerNorm,self).__init__() 115 | self.a_2 = nn.Parameter(torch.ones(features)) 116 | self.b_2 = nn.Parameter(torch.zeros(features)) 117 | self.eps = eps 118 | def forward(self, x): 119 | mean = x.mean(-1, keepdim =True) # 평균 120 | std = x.std(-1, keepdim=True) # 표준편차 121 | 122 | return self.a_2 * (x-mean)/ (std + self.eps) + self.b_2 123 | 124 | class ResidualConnection(nn.Module): 125 | def __init__(self, size, dropout): 126 | super(ResidualConnection,self).__init__() 127 | self.norm = LayerNorm(size) 128 | self.dropout = nn.Dropout(dropout) 129 | 130 | def forward(self, x, sublayer): 131 | return x + self.dropout((sublayer(self.norm(x)))) 132 | 133 | class Residual(nn.Module): 134 | def __init__(self, dropout): 135 | super(Residual,self).__init__() 136 | self.dropout = nn.Dropout(dropout) 137 | 138 | def forward(self, x, sublayer_output): 139 | return x + self.dropout(sublayer_output) 140 | 141 | class Decoder(nn.Module): 142 | def __init__(self, d_model,head_num, dropout, rezero_use = True, explicit_sparse_attn_topk=8, macaron_net_use = False, residual_attn=False): 143 | """ 144 | d_model: model hidden dimension 145 | head_num: number of attention head 146 | dropout: dropout probablity 147 | rezero_use = True : ReZero use or not 148 | explicit_sparse_attn_topk=8: Explicit sparse attention top-k. The origin paper suggest topk = 8. keep only the top 8 values before attention (softmax) 149 | """ 150 | super(Decoder,self).__init__() 151 | 152 | # Macaron Architecture 153 | self.macaron = macaron_net_use 154 | 155 | if self.macaron: 156 | self.macaron_net = Scale(0.5,FeedForward(d_model, d_model)) 157 | 158 | self.masked_multi_head_attention = MultiHeadAttention(d_model= d_model, head_num= head_num, causal=True, explicit_sparse_attn_topk=explicit_sparse_attn_topk, residual_attn=residual_attn) 159 | self.residual_1 = ReZero(dropout) if rezero_use else Residual(dropout=dropout) 160 | 161 | self.feed_forward = FeedForward(d_model) 162 | if self.macaron: 163 | self.feed_forward = Scale(0.5, self.feed_forward) 164 | self.residual_2 = ReZero(dropout) if rezero_use else Residual(dropout=dropout) 165 | 166 | 167 | def forward(self, input): 168 | x, prev_attn = input 169 | if self.macaron: 170 | x = self.macaron_net(x) 171 | # target = self.residual_1(target, lambda x: self.masked_multi_head_attention(x, x, x)) 172 | # target = self.residual_2(target, lambda x: self.feed_forward(x)) 173 | 174 | x, pre_softmax_attn = self.masked_multi_head_attention(query=x, key=x, value=x, prev_attn=prev_attn) 175 | x = self.residual_1(x) 176 | 177 | x = self.feed_forward(x) 178 | x = self.residual_2(x) 179 | 180 | return (x, pre_softmax_attn) 181 | 182 | class PositionalEmbedding(nn.Module): 183 | def __init__(self, dim, max_seq_len): 184 | super().__init__() 185 | self.embedding = nn.Embedding(max_seq_len, dim) 186 | 187 | def forward(self, x): 188 | t = torch.arange(x.shape[1], device=x.device) 189 | return self.embedding(t) 190 | 191 | 192 | class ReZero(nn.Module): 193 | def __init__(self, dropout): 194 | super().__init__() 195 | self.g = nn.Parameter(torch.zeros(1)) 196 | self.dropout = nn.Dropout(dropout) 197 | 198 | def forward(self, x): 199 | x = x * self.g 200 | return x + self.dropout(x) 201 | 202 | class Embedding(nn.Module): 203 | def __init__(self, vocab_size, dim, max_seq_len): 204 | self.token_emb = nn.Embedding(vocab_size, dim) 205 | self.position_emb = PositionalEmbedding(dim, max_seq_len) 206 | def forward(self, input_ids): 207 | x= self.token_emb(input_ids) 208 | x= x+self.position_emb(input_ids).type_as(x) 209 | 210 | return x 211 | class GPTX(nn.Module): 212 | def __init__(self, 213 | vocab_size, 214 | dim, 215 | depth, 216 | max_seq_len, 217 | head_num, 218 | dropout=0.1): 219 | super(GPTX, self).__init__() 220 | 221 | # Embedding 222 | self.embedding = Embedding(vocab_size, dim, max_seq_len) 223 | 224 | # Decoders 225 | self.decoders = nn.Sequential(*[ Decoder(d_model=dim, head_num=head_num, dropout=dropout) for _ in range(depth) ]) 226 | 227 | self.norm = nn.LayerNorm(dim) 228 | self.lm_head = nn.Linear(dim, vocab_size, bias=False) 229 | 230 | def forward(self, input_ids, labels): 231 | pre_attn = None 232 | 233 | x = self.embedding(input_ids) 234 | x = self.decoders((x,pre_attn)) 235 | 236 | lm_logits = self.lm_head(x[0]) 237 | 238 | loss = None 239 | if labels is not None: 240 | # Shift so that tokens < n predict n 241 | shift_logits = lm_logits[..., :-1, :].contiguous() 242 | shift_labels = labels[..., 1:].contiguous() 243 | 244 | # Flatten the tokens 245 | loss_fn = CrossEntropyLoss() 246 | loss = loss_fn(shift_logits.view(-1, shift_logits.size(-1)), shift_labels.view(-1)) 247 | 248 | return lm_logits, loss 249 | 250 | class LitGPTX(pl.LightningModule): 251 | def __init__(self, 252 | vocab_size, 253 | dim, 254 | depth, 255 | max_seq_len, 256 | head_num, 257 | dropout=0.1): 258 | super(LitGPTX, self).__init__() 259 | 260 | # Embedding 261 | self.token_emb = nn.Embedding(vocab_size, dim) 262 | self.position_emb = PositionalEmbedding(dim, max_seq_len) 263 | 264 | # Decoders 265 | self.decoders = nn.ModuleList([Decoder(d_model=dim, head_num=head_num, dropout=dropout) for _ in range(depth)]) 266 | 267 | self.norm = nn.LayerNorm(dim) 268 | self.lm_head = nn.Linear(dim, vocab_size, bias=False) 269 | 270 | def configure_optimizers(self): 271 | # DeepSpeedCPUAdam provides 5x, 7x speedup over torch.optim.adma(w) 272 | return DeepSpeedCPUAdam(model_params=self.parameters(), 273 | lr=1e-5) 274 | # return FusedAdam(self.parameters()) 275 | 276 | def forward(self, input_ids, labels): 277 | x = self.token_emb(input_ids) 278 | x = x + self.position_emb(input_ids).type_as(x) 279 | 280 | pre_attn = None 281 | for decoder in self.decoders: 282 | x, pre_attn = decoder(x, pre_attn) 283 | 284 | lm_logits = self.lm_head(x) 285 | 286 | loss = None 287 | if labels is not None: 288 | # Shift so that tokens < n predict n 289 | shift_logits = lm_logits[..., :-1, :].contiguous() 290 | shift_labels = labels[..., 1:].contiguous() 291 | 292 | # Flatten the tokens 293 | loss_fn = CrossEntropyLoss() 294 | loss = loss_fn(shift_logits.view(-1, shift_logits.size(-1)), shift_labels.view(-1)) 295 | 296 | return lm_logits, loss 297 | 298 | def training_step(self, train_batch, batch_idx): 299 | input_ids, labels = train_batch 300 | lm_logits, loss = self.forward(input_ids, labels) 301 | perplexity = torch.exp(loss) 302 | 303 | self.log('train_loss', loss, prog_bar=True) 304 | self.log('train_ppl', perplexity, prog_bar=True) 305 | 306 | tb_logs = {'train_loss':loss, 'train_ppl':perplexity} 307 | 308 | return {'loss':loss, 'log': tb_logs} 309 | 310 | def validation_step(self, val_batch, batch_idx): 311 | input_ids, labels = val_batch 312 | lm_logits, loss = self.forward(input_ids, labels) 313 | perplexity = torch.exp(loss) 314 | 315 | self.log('val_loss', loss, prog_bar=True) 316 | self.log('val_ppl', perplexity, prog_bar=True) 317 | 318 | tb_logs = {'val_loss': loss, 'val_ppl': perplexity} 319 | 320 | return {'loss': loss, 'log': tb_logs} 321 | 322 | def validation_epoch_end(self, outputs): 323 | loss, avg_ppl = 0, 0 324 | avg_loss = torch.stack([x['loss'] for x in outputs]).mean() 325 | for x in outputs: 326 | avg_ppl += x['log']['val_ppl'] 327 | avg_ppl/len(outputs) 328 | logs = {'avg_val_loss':avg_loss, 'avg_val_ppl':avg_ppl} 329 | 330 | return {'avg_val_loss': avg_loss, 'avg_val_ppl': avg_ppl, 'log': logs, 'progress_bar': logs} 331 | 332 | 333 | if __name__=='__main__': 334 | pass 335 | -------------------------------------------------------------------------------- /model/pipeline.py: -------------------------------------------------------------------------------- 1 | # from model.n_transformer import GPTX 2 | from model.transformer import ReZeroSparseTopkGPT 3 | import deepspeed 4 | 5 | # class GPTXPipe(GPTX): 6 | # def to_layer(self): 7 | # layers=[ 8 | # self.embedding, 9 | # *self.decoders, 10 | # self.norm, 11 | # self.lm_head 12 | # ] 13 | # return layers 14 | 15 | class ReZroSparseTopkGPTPipe(ReZeroSparseTopkGPT): 16 | def to_layer(self): 17 | layers = [ 18 | self.embedding, 19 | *self.decoders, 20 | self.norm, 21 | self.lm_head 22 | ] 23 | return layers 24 | 25 | def forward(self, input_ids): 26 | x = self.embedding(input_ids) 27 | x = self.decoders(x) 28 | lm_logits = self.lm_head(x) 29 | 30 | return lm_logits 31 | -------------------------------------------------------------------------------- /model/transformer.py: -------------------------------------------------------------------------------- 1 | import math 2 | import torch 3 | import torch.nn as nn 4 | import torch.nn.functional as F 5 | from torch.nn import CrossEntropyLoss 6 | import pytorch_lightning as pl 7 | from deepspeed.ops.adam import DeepSpeedCPUAdam 8 | 9 | def self_attention(query, key, value, mask=None, causal=False): 10 | key_transpose = torch.transpose(key,-2,-1) # (bath, n_head, d_k, token_) 11 | matmul_result = torch.matmul(query,key_transpose) # MatMul(Q,K) 12 | d_k = query.size()[-1] 13 | attention_score = matmul_result/math.sqrt(d_k) # Scale 14 | 15 | if mask is not None: 16 | attention_score = attention_score.masked_fill(mask == 0, -1e20) 17 | # is Decoder 18 | if causal: 19 | query_len = query.size()[2] 20 | i, j = torch.triu_indices(query_len, query_len, 1) 21 | attention_score[:, :, i, j] = -1e4 22 | 23 | softmax_attention_score = F.softmax(attention_score,dim=-1) # 어텐션 값 24 | result = torch.matmul(softmax_attention_score,value) 25 | 26 | return result, softmax_attention_score 27 | 28 | 29 | class MultiHeadAttention(nn.Module): 30 | def __init__(self, n_head =8 , d_model = 512,dropout = 0.1, causal=False): 31 | super(MultiHeadAttention,self).__init__() 32 | 33 | self.n_head = n_head 34 | self.d_model = d_model 35 | self.d_k = self.d_v = d_model // n_head 36 | self.causal = causal 37 | 38 | self.w_q = nn.Linear(d_model,d_model) 39 | self.w_k = nn.Linear(d_model,d_model) 40 | self.w_v = nn.Linear(d_model,d_model) 41 | self.w_o = nn.Linear(d_model,d_model) 42 | 43 | self.self_attention = self_attention 44 | self.dropout = nn.Dropout(p=dropout) 45 | 46 | def forward(self, query, key, value, mask = None): 47 | if mask is not None: 48 | # Same mask applied to all h heads. 49 | mask = mask.unsqueeze(1) 50 | 51 | batche_num = query.size(0) 52 | 53 | query = self.w_q(query).view(batche_num, -1, self.n_head, self.d_k).transpose(1, 2) 54 | key = self.w_k(key).view(batche_num, -1, self.n_head, self.d_k).transpose(1, 2) 55 | value = self.w_v(value).view(batche_num, -1, self.n_head, self.d_k).transpose(1, 2) 56 | 57 | attention_result, attention_score = self.self_attention(query, key, value, mask, self.causal) 58 | attention_result = attention_result.transpose(1,2).contiguous().view(batche_num, -1, self.n_head * self.d_k) 59 | attn_output = self.w_o(attention_result) 60 | 61 | 62 | return attn_output 63 | 64 | def explicit_sparse_attention(q, k ,v, mask=None, causal=None, sparse_topk=8): 65 | key_transose = torch.transpose(k,-2, -1) 66 | dot = torch.matmul(q, key_transose) 67 | 68 | head_dim = q.size()[-1] 69 | dot = dot / head_dim ** 0.5 70 | 71 | # Encoder input mask 72 | if mask: 73 | dot = dot.masked_fill(mask, 1e-4) 74 | 75 | # Causal Look-Ahead mask 76 | if causal: 77 | q_length = q.size()[2] 78 | i,j = torch.triu_indices(q_length, q_length,1) 79 | dot[:, :, i, j] = -1e4 80 | 81 | # Explicit sparse attention mask 82 | if sparse_topk > 0: 83 | topk, _ = dot.topk(sparse_topk,dim=-1) 84 | vk = topk[...,-1].unsqueeze(-1).expand_as(dot) 85 | explicit_sparse_mask = dot < vk # vk보다 낮은값들이 true 86 | dot.masked_fill(explicit_sparse_mask, -1e4) 87 | 88 | attn_score = F.softmax(dot,dim=-1) 89 | attn_value = torch.matmul(attn_score, v) 90 | 91 | return attn_value, attn_score 92 | 93 | class SparseTopkMultiHeadAttention(nn.Module): 94 | def __init__(self, d_model, n_head, dropout=0.1, causal=False, sparse_topk=8): 95 | super().__init__() 96 | self.d_model=d_model 97 | self.k_head_dim = d_model//n_head 98 | self.v_head_dim = d_model//n_head 99 | 100 | self.n_head=n_head 101 | self.dropout=dropout 102 | self.causal=causal 103 | self.sparse_topk=sparse_topk 104 | 105 | self.w_query = nn.Linear(d_model, d_model) 106 | self.w_key = nn.Linear(d_model, d_model) 107 | self.w_value = nn.Linear(d_model, d_model) 108 | 109 | self.w_out = nn.Linear(d_model, d_model) 110 | self.self_attention = explicit_sparse_attention 111 | 112 | self.dropout=nn.Dropout(dropout) 113 | 114 | def forward(self, q, k, v, mask=None): 115 | if mask is not None: 116 | mask = mask.unsqueeze(1) 117 | 118 | batch_size = q.size()[0] 119 | query = self.w_query(q).view(batch_size, -1, self.n_head, self.k_head_dim).transpose(1,2) 120 | key = self.w_key(k).view(batch_size, -1, self.n_head, self.k_head_dim).transpose(1,2) 121 | value = self.w_value(v).view(batch_size, -1, self.n_head, self.v_head_dim).transpose(1,2) 122 | 123 | attn_value, attn_score = self.self_attention(q=query, k=key, v=value, mask=mask,sparse_topk=self.sparse_topk) 124 | attn_value = attn_value.transpose(1,2).contiguous().view(batch_size, -1, self.n_head * self.k_head_dim) 125 | 126 | attn_value = self.w_out(attn_value) 127 | 128 | return self.dropout(attn_value) 129 | 130 | class FeedForward(nn.Module): 131 | def __init__(self, d_model, dropout=0.1, activation='gelu'): 132 | super(FeedForward, self).__init__() 133 | self.w_1 = nn.Linear(d_model, d_model * 4) 134 | self.w_2 = nn.Linear(d_model * 4, d_model) 135 | self.dropout = nn.Dropout(p=dropout) 136 | 137 | if activation == 'gelu': 138 | self.activation = F.gelu 139 | elif activation == 'relu': 140 | self.activation = F.relu 141 | 142 | def forward(self, x): 143 | return self.w_2(self.dropout(self.activation(self.w_1(x)))) 144 | 145 | 146 | class LayerNorm(nn.Module): 147 | def __init__(self, features, eps=1e-6): 148 | super(LayerNorm,self).__init__() 149 | self.a_2 = nn.Parameter(torch.ones(features)) 150 | self.b_2 = nn.Parameter(torch.zeros(features)) 151 | self.eps = eps 152 | def forward(self, x): 153 | mean = x.mean(-1, keepdim =True) # 평균 154 | std = x.std(-1, keepdim=True) # 표준편차 155 | 156 | return self.a_2 * (x-mean)/ (std + self.eps) + self.b_2 157 | 158 | class ResidualConnection(nn.Module): 159 | def __init__(self, size, dropout): 160 | super(ResidualConnection,self).__init__() 161 | self.norm = LayerNorm(size) 162 | self.dropout = nn.Dropout(dropout) 163 | 164 | def forward(self, x, sublayer): 165 | return x + self.dropout((sublayer(self.norm(x)))) 166 | 167 | class Residual(nn.Module): 168 | def __init__(self, dropout): 169 | super(Residual,self).__init__() 170 | self.dropout = nn.Dropout(dropout) 171 | 172 | def forward(self, x, sublayer_output): 173 | return x + self.dropout(sublayer_output) 174 | 175 | class Decoder(nn.Module): 176 | def __init__(self, d_model,n_head, dropout): 177 | super(Decoder,self).__init__() 178 | self.masked_multi_head_attention = MultiHeadAttention(d_model= d_model, n_head= n_head,causal=True) 179 | self.residual_1 = ResidualConnection(d_model,dropout=dropout) 180 | 181 | self.feed_forward= FeedForward(d_model) 182 | self.residual_2 = ResidualConnection(d_model,dropout=dropout) 183 | 184 | 185 | def forward(self, x): 186 | x = self.residual_1(x, lambda x: self.masked_multi_head_attention(x, x, x)) 187 | x = self.residual_2(x, self.feed_forward) 188 | 189 | return x 190 | 191 | class RZDecoder(nn.Module): 192 | def __init__(self, d_model,n_head, dropout): 193 | super().__init__() 194 | self.masked_multi_head_attention = MultiHeadAttention(d_model=d_model, n_head=n_head, dropout=dropout) 195 | self.rezero_1 = ReZero(dropout) 196 | 197 | self.feed_forward = FeedForward(d_model) 198 | self.rezero_2 = ReZero(dropout) 199 | def forward(self, x): 200 | x_1 = self.masked_multi_head_attention(x,x,x) 201 | x = x + self.rezero_1(x_1) 202 | 203 | x_2 = self.feed_forward(x) 204 | x = x + self.rezero_2(x_2) 205 | 206 | return x 207 | 208 | class ReZeroSparseTopkDecoder(nn.Module): 209 | def __init__(self, d_model,n_head, dropout, sparse_topk=8): 210 | super().__init__() 211 | self.masked_multi_head_attention = SparseTopkMultiHeadAttention(d_model=d_model, n_head=n_head, dropout=dropout, causal=True, sparse_topk=sparse_topk) 212 | self.rezero_1 = ReZero(dropout) 213 | 214 | self.feed_forward = FeedForward(d_model) 215 | self.rezero_2 = ReZero(dropout) 216 | 217 | def forward(self, x): 218 | x_1 = self.masked_multi_head_attention(x,x,x) 219 | x = x + self.rezero_1(x_1) 220 | 221 | x_2 = self.feed_forward(x) 222 | x = x + self.rezero_2(x_2) 223 | 224 | return x 225 | 226 | class ReZero(nn.Module): 227 | def __init__(self, dropout): 228 | super().__init__() 229 | self.res_weight = nn.Parameter(torch.Tensor([0])) 230 | self.dropout = nn.Dropout(dropout) 231 | 232 | def forward(self, x): 233 | x = self.dropout(x) * self.res_weight 234 | 235 | return x 236 | 237 | class Embedding(nn.Module): 238 | def __init__(self, vocab_size, dim, max_seq_len): 239 | super().__init__() 240 | self.token_emb = nn.Embedding(vocab_size, dim) 241 | self.position_emb = PositionalEmbedding(dim, max_seq_len) 242 | def forward(self, input_ids): 243 | x= self.token_emb(input_ids) 244 | x= x+self.position_emb(input_ids).type_as(x) 245 | return x 246 | 247 | class PositionalEmbedding(nn.Module): 248 | def __init__(self, dim, max_seq_len): 249 | super().__init__() 250 | self.embedding = nn.Embedding(max_seq_len, dim) 251 | 252 | def forward(self, x): 253 | t = torch.arange(x.shape[1], device=x.device) 254 | return self.embedding(t) 255 | 256 | class GPT2(nn.Module): 257 | def __init__(self, 258 | vocab_size, 259 | dim, 260 | depth, 261 | max_seq_len, 262 | n_head, 263 | dropout=0.1): 264 | super(GPT2, self).__init__() 265 | 266 | # Embedding 267 | self.embedding = Embedding(vocab_size, dim, max_seq_len) 268 | 269 | # Decoders 270 | self.decoders = nn.Sequential(*[Decoder(d_model=dim, n_head=n_head, dropout=dropout) for _ in range(depth)]) 271 | 272 | self.norm = nn.LayerNorm(dim) 273 | self.lm_head = nn.Linear(dim, vocab_size, bias=False) 274 | 275 | def forward(self, input_ids, labels): 276 | 277 | x = self.embedding(input_ids) 278 | x = self.decoders(x) 279 | 280 | lm_logits = self.lm_head(x) 281 | 282 | loss = None 283 | if labels is not None: 284 | # Shift so that tokens < n predict n 285 | shift_logits = lm_logits[..., :-1, :].contiguous() 286 | shift_labels = labels[..., 1:].contiguous() 287 | 288 | # Flatten the tokens 289 | loss_fn = CrossEntropyLoss() 290 | loss = loss_fn(shift_logits.view(-1, shift_logits.size(-1)), shift_labels.view(-1)) 291 | 292 | return lm_logits, loss 293 | 294 | class ReZeroSparseTopkGPT(nn.Module): 295 | def __init__(self, 296 | vocab_size, 297 | dim, 298 | depth, 299 | max_seq_len, 300 | n_head, 301 | dropout=0.1): 302 | super(ReZeroSparseTopkGPT, self).__init__() 303 | 304 | # Embedding 305 | self.embedding = Embedding(vocab_size, dim, max_seq_len) 306 | 307 | # Decoders 308 | self.decoders = nn.Sequential(*[ReZeroSparseTopkDecoder(d_model=dim, n_head=n_head, dropout=dropout) for _ in range(depth)]) 309 | 310 | self.norm = nn.LayerNorm(dim) 311 | self.lm_head = nn.Linear(dim, vocab_size, bias=False) 312 | 313 | def forward(self, input_ids, labels): 314 | 315 | x = self.embedding(input_ids) 316 | x = self.decoders(x) 317 | 318 | lm_logits = self.lm_head(x) 319 | 320 | loss = None 321 | if labels is not None: 322 | # Shift so that tokens < n predict n 323 | shift_logits = lm_logits[..., :-1, :].contiguous() 324 | shift_labels = labels[..., 1:].contiguous() 325 | 326 | # Flatten the tokens 327 | loss_fn = CrossEntropyLoss() 328 | loss = loss_fn(shift_logits.view(-1, shift_logits.size(-1)), shift_labels.view(-1)) 329 | 330 | return lm_logits, loss 331 | 332 | class LitGPT2(pl.LightningModule): 333 | def __init__(self, 334 | vocab_size, 335 | dim, 336 | depth, 337 | max_seq_len, 338 | head_num, 339 | dropout=0.1): 340 | super(LitGPT2, self).__init__() 341 | 342 | # Embedding 343 | self.embedding = Embedding(vocab_size, dim, max_seq_len) 344 | 345 | # Decoders 346 | # self.decoders = nn.Sequential(*[Decoder(d_model=dim, n_head=head_num, dropout=dropout) for _ in range(depth)]) 347 | # self.decoders = nn.Sequential(*[RZDecoder(d_model=dim, n_head=head_num, dropout=dropout) for _ in range(depth)]) 348 | self.decoders = nn.Sequential(*[ReZeroSparseTopkDecoder(d_model=dim, n_head=head_num, dropout=dropout) for _ in range(depth)]) 349 | 350 | self.norm = nn.LayerNorm(dim) 351 | self.lm_head = nn.Linear(dim, vocab_size, bias=False) 352 | 353 | def configure_optimizers(self): 354 | # DeepSpeedCPUAdam provides 5x, 7x speedup over torch.optim.adma(w) 355 | return DeepSpeedCPUAdam(model_params=self.parameters(), 356 | lr=5e-4) 357 | # return FusedAdam(self.parameters()) 358 | 359 | def forward(self, input_ids, labels): 360 | x = self.embedding(input_ids) 361 | x = self.decoders(x) 362 | 363 | lm_logits = self.lm_head(x) 364 | 365 | loss = None 366 | if labels is not None: 367 | # Shift so that tokens < n predict n 368 | shift_logits = lm_logits[..., :-1, :].contiguous() 369 | shift_labels = labels[..., 1:].contiguous() 370 | 371 | # Flatten the tokens 372 | loss_fn = CrossEntropyLoss() 373 | loss = loss_fn(shift_logits.view(-1, shift_logits.size(-1)), shift_labels.view(-1)) 374 | 375 | return lm_logits, loss 376 | 377 | def training_step(self, train_batch, batch_idx): 378 | input_ids, labels = train_batch 379 | lm_logits, loss = self.forward(input_ids, labels) 380 | perplexity = torch.exp(loss) 381 | 382 | self.log('train_loss', loss, prog_bar=True) 383 | self.log('train_ppl', perplexity, prog_bar=True) 384 | 385 | tb_logs = {'train_loss':loss, 'train_ppl':perplexity} 386 | 387 | return {'loss':loss, 'log': tb_logs} 388 | 389 | def validation_step(self, val_batch, batch_idx): 390 | input_ids, labels = val_batch 391 | lm_logits, loss = self.forward(input_ids, labels) 392 | perplexity = torch.exp(loss) 393 | 394 | self.log('val_loss', loss, prog_bar=True) 395 | self.log('val_ppl', perplexity, prog_bar=True) 396 | 397 | tb_logs = {'val_loss': loss, 'val_ppl': perplexity} 398 | 399 | return {'loss': loss, 'log': tb_logs} 400 | 401 | def validation_epoch_end(self, outputs): 402 | loss, avg_ppl = 0, 0 403 | avg_loss = torch.stack([x['loss'] for x in outputs]).mean() 404 | for x in outputs: 405 | avg_ppl += x['log']['val_ppl'] 406 | avg_ppl/len(outputs) 407 | logs = {'avg_val_loss':avg_loss, 'avg_val_ppl':avg_ppl} 408 | 409 | return {'avg_val_loss': avg_loss, 'avg_val_ppl': avg_ppl, 'log': logs, 'progress_bar': logs} 410 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | torch 2 | wandb 3 | transformers 4 | reformer_pytorch 5 | fairseq 6 | deepspeed 7 | pytorch_lightning -------------------------------------------------------------------------------- /train/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "vocab_path" : "../data/vocab-v1.txt", 3 | "data_path" :"../data/train/" , 4 | "checkpoint_path" : "../checkpoints", 5 | "model_name": "gpt2", 6 | "vocab_size": 22000, 7 | "dim": 256, 8 | "depth": 6, 9 | "n_head": 32, 10 | "max_seq_len" : 1024, 11 | "dropout_prob": 0.3, 12 | "weight_decay": 0.01, 13 | "epochs": 20, 14 | "batch_size" : 2, 15 | "lr": 5e-4, 16 | "adam_epsilon":1e-6, 17 | "ckpt_steps" : 100000, 18 | "log_steps": 1, 19 | "log_dir": "../", 20 | "gradient_accumulation_steps": 8, 21 | "fp16": true, 22 | "fp16_opt_level": "O2" 23 | } 24 | -------------------------------------------------------------------------------- /train/run_pretraining.py: -------------------------------------------------------------------------------- 1 | import warnings 2 | 3 | warnings.filterwarnings("ignore") 4 | import sys 5 | 6 | sys.path.append('../') # for local 7 | # sys.path.append('/content/drive/My Drive/Colab Notebooks/transformer-electra') # for colab 8 | 9 | import torch 10 | import torch.nn as nn 11 | from torch.utils.data import DataLoader, random_split 12 | from tqdm import tqdm 13 | from transformers import BertTokenizer 14 | from transformers.optimization import AdamW 15 | 16 | if torch.cuda.is_available(): 17 | from apex import amp 18 | import os 19 | import json 20 | import logging 21 | from datetime import datetime 22 | 23 | from common.arg import ModelConfig 24 | from model.transformer import GPT2 25 | from common.dataset import GPTXDatasetV2 26 | 27 | 28 | class GPT2Trainer(object): 29 | def __init__(self, 30 | dataset, 31 | model, 32 | tokenizer, 33 | max_len, 34 | model_name, 35 | checkpoint_path, 36 | device=None, 37 | train_batch_size=8, 38 | eval_batch_size=None, 39 | log_dir='../logs', 40 | fp16=True): 41 | self.dataset = dataset 42 | self.model = model 43 | self.tokenizer = tokenizer 44 | self.max_len = max_len 45 | self.model_name = model_name 46 | self.checkpoint_path = checkpoint_path 47 | self.device = device 48 | self.n_gpu = torch.cuda.device_count() if torch.cuda.is_available() else 0 49 | self.train_batch_size = train_batch_size 50 | self.eval_batch_size = eval_batch_size 51 | self.log_dir = log_dir 52 | self.fp16 = fp16 53 | 54 | if device is None: 55 | self.device = 'cuda:0' if torch.cuda.is_available() else 'cpu' 56 | 57 | if eval_batch_size is None: 58 | self.eval_batch_size = train_batch_size 59 | 60 | logging.basicConfig(filename=f'{log_dir}/{self.model_name}-{datetime.now().date()}.log', level=logging.INFO) 61 | 62 | def build_dataloaders(self, train_test_split=0.1, train_shuffle=True, eval_shuffle=True): 63 | dataset_len = len(self.dataset) 64 | eval_len = int(dataset_len * train_test_split) 65 | train_len = dataset_len - eval_len 66 | train_dataset, eval_dataset = random_split(self.dataset, (train_len, eval_len)) 67 | train_loader = DataLoader(train_dataset, batch_size=self.train_batch_size, shuffle=train_shuffle) 68 | eval_loader = DataLoader(eval_dataset, batch_size=self.eval_batch_size, shuffle=eval_shuffle) 69 | logging.info(f'''train_dataloader size: {len(train_loader.dataset)} | shuffle: {train_shuffle} 70 | eval_dataloader size: {len(eval_loader.dataset)} | shuffle: {eval_shuffle}''') 71 | 72 | return train_loader, eval_loader 73 | 74 | def train(self, 75 | epochs, 76 | train_dataloader, 77 | eval_dataloader, 78 | optimizer, 79 | scheduler, 80 | log_steps, 81 | ckpt_steps, 82 | gradient_accumulation_steps=1): 83 | 84 | losses = {} 85 | global_steps = 0 86 | local_steps = 0 87 | step_loss = 0.0 88 | start_epoch = 0 89 | start_step = 0 90 | step_perplexity = 0.0 91 | 92 | self.model.train() 93 | self.model.to(self.device) 94 | 95 | logging.info(f'{datetime.now()} | Moved model to: {self.device}') 96 | logging.info( 97 | f'{datetime.now()} | train_batch_size: {self.train_batch_size} | eval_batch_size: {self.eval_batch_size}') 98 | logging.info(f'{datetime.now()} | Epochs: {epochs} | log_steps: {log_steps} | ckpt_steps: {ckpt_steps}') 99 | logging.info(f'{datetime.now()} | gradient_accumulation_steps: {gradient_accumulation_steps}') 100 | 101 | self.model.zero_grad() # Reset gradients tensors 102 | for epoch in range(start_epoch, epochs): # tqdm(range(epochs), desc='Epochs', position=0): 103 | logging.info(f'{datetime.now()} | Epoch: {epoch}') 104 | pb = tqdm(enumerate(train_dataloader), 105 | desc=f'Epoch-{epoch} Iterator', 106 | total=len(train_dataloader), 107 | bar_format='{l_bar}{bar:10}{r_bar}' 108 | ) 109 | for step, batch in pb: 110 | if step < start_step: 111 | continue 112 | inputs, labels = batch # _ is input_mask 113 | inputs, labels = inputs.to(self.device), labels.to(self.device) 114 | lm_logits, loss = self.model(inputs, labels) 115 | 116 | step_perplexity = torch.exp(loss) 117 | origin_loss = loss.item() 118 | 119 | loss = loss / gradient_accumulation_steps # divide loss into gradient accumulation step 120 | if self.fp16: 121 | with amp.scale_loss(loss, optimizer) as scaled_loss: 122 | scaled_loss.backward() 123 | else: 124 | loss.backward() 125 | 126 | step_loss = origin_loss 127 | losses[global_steps] = origin_loss 128 | 129 | local_steps += 1 130 | global_steps += 1 131 | 132 | if global_steps % gradient_accumulation_steps == 0: 133 | # torch.nn.utils.clip_grad_norm_(self.model.parameters(), max_norm=1.0) 134 | if self.fp16: 135 | torch.nn.utils.clip_grad_norm_(amp.master_params(optimizer), max_norm=1.0) 136 | else: 137 | torch.nn.utils.clip_grad_norm_(self.model.parameters(), max_norm=1.0) 138 | 139 | scheduler.step() 140 | optimizer.step() 141 | self.model.zero_grad() 142 | 143 | if global_steps % log_steps == 0: 144 | pb.set_postfix_str(f'''{datetime.now()} | Train Loss: {step_loss} | Train PPL: {step_perplexity} | Steps: {global_steps}''') 145 | step_loss = 0.0 146 | local_steps = 0 147 | 148 | if global_steps % ckpt_steps == 0: 149 | self.save(epoch, self.model, optimizer, scheduler, losses, global_steps) 150 | logging.info(f'{datetime.now()} | Saved checkpoint to: {self.checkpoint_path}') 151 | with open(f'{self.log_dir}/{self.model_name}_train_results.json', 'w') as results_file: 152 | json.dump(losses, results_file) 153 | results_file.close() 154 | 155 | # Evaluate every epoch 156 | self.evaluate(eval_dataloader) 157 | self.model.train() 158 | start_step = 0 159 | 160 | self.save(epoch, self.model, optimizer, scheduler, losses, global_steps) 161 | 162 | return self.model 163 | 164 | def evaluate(self, dataloader): 165 | self.model.eval() 166 | 167 | eval_loss = 0.0 168 | perplexity = 0.0 169 | eval_steps = 0 170 | 171 | logging.info(f'{datetime.now()} | Evaluating...') 172 | for step, batch in tqdm(enumerate(dataloader), 173 | desc='Evaluating', 174 | leave=True, 175 | total=len(dataloader), 176 | bar_format='{l_bar}{bar:10}{r_bar}'): 177 | 178 | inputs, labels = batch # _ is input_mask 179 | inputs, labels = inputs.to(self.device), labels.to(self.device) 180 | with torch.no_grad(): 181 | lm_logits, loss = self.model(inputs, labels) 182 | 183 | tmp_eval_loss = loss 184 | tmp_perplexity = torch.exp(tmp_eval_loss) 185 | 186 | eval_loss += tmp_eval_loss.item() 187 | perplexity += tmp_perplexity.item() 188 | eval_steps += 1 189 | 190 | total_eval_loss = eval_loss / eval_steps 191 | total_perplexity = perplexity / eval_steps 192 | 193 | logging.info(f'{datetime.now()} | Step: {step} | Eval Loss: {total_eval_loss} | Perplexity: {total_perplexity}') 194 | with open(f'{self.log_dir}/{self.model_name}_eval_results.txt', 'a+') as results_file: 195 | results_file.write( 196 | f'{datetime.now()} | Step: {step} | Eval Loss: {total_eval_loss} | Perplexity: {total_perplexity}\n') 197 | results_file.close() 198 | 199 | def save(self, epoch, model, optimizer, scheduler, losses, train_step): 200 | torch.save({ 201 | 'epoch': epoch, # 현재 학습 epoch 202 | 'model_state_dict': model.state_dict(), # 모델 저장 203 | 'optimizer_state_dict': optimizer.state_dict(), # 옵티마이저 저장 204 | 'scheduler_state_dict': scheduler.state_dict(), # 스케줄러 205 | 'losses': losses, # Loss 저장 206 | 'train_step': train_step, # 현재 진행한 학습 207 | 'amp': amp.state_dict() 208 | }, f'{self.checkpoint_path}/{self.model_name}.pth') 209 | def gptx_dataset(config, tokenizer, dataset_func): 210 | cache_data_path = f'{config.checkpoint_path}/{config.model_name}.pickle' 211 | cache_dir_path= os.path.dirname(cache_data_path) 212 | 213 | if os.path.exists(cache_data_path): # 캐시 데이터가 존재하는 경우 214 | dataset = torch.load(cache_data_path) 215 | return dataset 216 | else: # 캐시 데이터가 없는 경우 217 | if not os.path.exists(cache_dir_path): 218 | os.makedirs(cache_dir_path) # 캐시 디렉토리 경로 생성 219 | 220 | dataset = dataset_func(tokenizer, config.max_seq_len, config.data_path) 221 | torch.save(dataset, cache_data_path) # 데이터 저장 222 | 223 | return dataset 224 | 225 | def main(): 226 | torch.manual_seed(9) 227 | base_path = '..' 228 | log_dir = f'{base_path}/logs' 229 | config_path = f'{base_path}/train/config.json' 230 | 231 | # Config 232 | config = ModelConfig(config_path=config_path).get_config() 233 | 234 | # Tokenizer 235 | tokenizer = BertTokenizer(vocab_file=config.vocab_path, do_lower_case=False) 236 | 237 | # Dataset 238 | # dataset = GPTXDatasetV2(tokenizer, config.max_seq_len, config.data_path) 239 | dataset = gptx_dataset(config, tokenizer, GPTXDatasetV2) 240 | 241 | # Logging 242 | logging.basicConfig(filename=f'{config.log_dir}/{config.model_name}-{datetime.now().date()}.log', level=logging.INFO) 243 | # 4. Electra Model 244 | model = GPT2(vocab_size=tokenizer.vocab_size, 245 | dim=config.dim, 246 | depth=config.depth, 247 | n_head=config.n_head, 248 | max_seq_len=config.max_seq_len) 249 | if torch.cuda.is_available(): 250 | model.cuda() 251 | 252 | # 5. Pretraining Traniner 253 | trainer = GPT2Trainer(dataset, model, tokenizer, 254 | model_name=config.model_name, 255 | max_len=config.max_seq_len, 256 | checkpoint_path=config.checkpoint_path, 257 | train_batch_size=config.batch_size, 258 | eval_batch_size=config.batch_size, 259 | log_dir=log_dir, 260 | fp16=config.fp16) 261 | 262 | train_dataloader, eval_dataloader = trainer.build_dataloaders(train_test_split=0.1) 263 | 264 | # Prepare optimizer 265 | param_optimizer = list(model.named_parameters()) 266 | no_decay = ['bias', 'LayerNorm.weight'] 267 | optimizer_grouped_parameters = [ 268 | {'params': [p for n, p in param_optimizer if not any(nd in n for nd in no_decay)], 269 | 'weight_decay': 0.01}, 270 | {'params': [p for n, p in param_optimizer if any(nd in n for nd in no_decay)], 271 | 'weight_decay': 0.0} 272 | ] 273 | 274 | learning_rate = 5e-4 275 | adam_epsilon = 1e-6 276 | 277 | optimizer = AdamW(optimizer_grouped_parameters, 278 | lr=learning_rate, 279 | eps=adam_epsilon) 280 | 281 | scheduler = torch.optim.lr_scheduler.OneCycleLR(optimizer, 282 | max_lr=5e-3, 283 | steps_per_epoch=len( 284 | train_dataloader) // config.gradient_accumulation_steps, 285 | epochs=config.epochs, 286 | pct_start=0.05, 287 | anneal_strategy='linear') 288 | 289 | if config.fp16: 290 | model, optimizer = amp.initialize(model, optimizer, opt_level=config.fp16_opt_level) 291 | 292 | trainer.train(epochs=config.epochs, 293 | train_dataloader=train_dataloader, 294 | eval_dataloader=eval_dataloader, 295 | optimizer=optimizer, 296 | scheduler=scheduler, 297 | log_steps=config.log_steps, 298 | ckpt_steps=config.ckpt_steps, 299 | gradient_accumulation_steps=config.gradient_accumulation_steps) 300 | 301 | 302 | if __name__ == '__main__': 303 | main() -------------------------------------------------------------------------------- /train_deepspeed/__pycache__/ds_util.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nawnoes/pytorch-gpt-x/6d6d8b3ef3c66a5f454e4a722fdbc26268312b89/train_deepspeed/__pycache__/ds_util.cpython-36.pyc -------------------------------------------------------------------------------- /train_deepspeed/config_rezero_sparsetopk.json: -------------------------------------------------------------------------------- 1 | { 2 | "vocab_path" : "../data/vocab-v1.txt", 3 | "data_path" :"../data/train/" , 4 | "checkpoint_path" : "../checkpoints", 5 | "cache_path": "../checkpoints", 6 | "model_name": "rezero_sparsetopk_gpt", 7 | "vocab_size": 22000, 8 | "dim": 2048, 9 | "depth": 20, 10 | "n_head": 16, 11 | "max_seq_len" : 1024, 12 | "dropout_prob": 0.3, 13 | "weight_decay": 0.01, 14 | "optimizer": { 15 | "type": "adam", 16 | "params": { 17 | "lr": 2e-4, 18 | "betas": [0.8, 0.999], 19 | "eps": 1e-8, 20 | "weight_decay": 3e-7 21 | } 22 | }, 23 | "epoch": 1, 24 | "batch_size" : 1, 25 | "max_train_step": null, 26 | "max_eval_step": null, 27 | "ckpt_steps" : 1000, 28 | "is_pipe_parallel": true, 29 | "num_stages": 2, 30 | "warmup_iter": 0.1 31 | } 32 | -------------------------------------------------------------------------------- /train_deepspeed/ds_config_rezero_sparsetopk.json: -------------------------------------------------------------------------------- 1 | { 2 | "train_batch_size" : 4, 3 | "train_micro_batch_size_per_gpu" : 1, 4 | "zero_optimization": { 5 | "stage":1, 6 | "allgather_partitions": true, 7 | "allgather_bucket_size": 500000000, 8 | "overlap_comm": true, 9 | "reduce_scatter": true, 10 | "reduce_bucket_size": 500000000, 11 | "contiguous_gradients": true, 12 | "cpu_offload": false 13 | }, 14 | "steps_per_print": 100, 15 | "wall_clock_breakdown" : false, 16 | "fp16": { 17 | "enabled": true, 18 | "loss_scale": 0, 19 | "initial_scale_power": 32, 20 | "loss_scale_window": 1000, 21 | "hysteresis": 2, 22 | "min_loss_scale": 1 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /train_deepspeed/ds_train_rezero_sparsetopk.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | base_dir=`pwd` 4 | 5 | JOB_NAME=deepspeed_rezero_sparsetopk_gpt 6 | 7 | deepspeed ${base_dir}/train_rezero_sparsetopk.py \ 8 | --config ${base_dir}/config_rezero_sparsetopk.json \ 9 | --deepspeed_config ${base_dir}/ds_config_rezero_sparsetopk.json \ 10 | # &> ${JOB_NAME}.log 11 | -------------------------------------------------------------------------------- /train_deepspeed/ds_util.py: -------------------------------------------------------------------------------- 1 | import sys 2 | import argparse 3 | 4 | 5 | def get_argument_parser(): 6 | parser = argparse.ArgumentParser() 7 | 8 | 9 | parser.add_argument('--finetune', 10 | default=False, 11 | action='store_true', 12 | help="Whether to finetune only") 13 | 14 | parser.add_argument( 15 | '--config', 16 | type=str, 17 | default='./config.json', 18 | help='Configuration path of json file for pretraining GPT-3 ' 19 | ) 20 | parser.add_argument( 21 | "--local_rank", 22 | type=int, 23 | default=-1, 24 | help="local_rank for distributed training on gpus" 25 | ) 26 | 27 | return parser 28 | 29 | 30 | def is_time_to_exit(args, epoch_steps=0, global_steps=0): 31 | return (epoch_steps >= args.max_steps_per_epoch) or \ 32 | (global_steps >= args.max_steps) -------------------------------------------------------------------------------- /train_deepspeed/train_rezero_sparsetopk.py: -------------------------------------------------------------------------------- 1 | import sys 2 | 3 | from torch.optim import lr_scheduler 4 | sys.path.append('../') 5 | 6 | import torch 7 | from torch.nn import CrossEntropyLoss 8 | from torch.utils.data import DataLoader, random_split 9 | import deepspeed 10 | from common.dataset import GPTXDatasetV2 11 | from common.arg import ModelConfig 12 | from model.pipeline import ReZroSparseTopkGPTPipe 13 | from transformers import BertTokenizer 14 | from ds_util import get_argument_parser 15 | from transformers import get_cosine_schedule_with_warmup 16 | from deepspeed.pipe import PipelineModule 17 | import wandb 18 | import os 19 | import logging 20 | from itertools import cycle 21 | 22 | 23 | logger = logging.getLogger("ReZeroSparsetopkGPTX") 24 | log_formatter = logging.Formatter( 25 | "%(asctime)s %(levelname)s [%(name)s] [%(filename)s:%(lineno)d] - %(message)s" 26 | ) 27 | stream_handler = logging.StreamHandler() 28 | stream_handler.setFormatter(log_formatter) 29 | 30 | logger.addHandler(stream_handler) 31 | logger.setLevel(logging.INFO) 32 | 33 | 34 | def pretrain(): 35 | """Main Train 36 | 1) setup model, optimizer and lr_schedule 37 | 2) set dataset 38 | 3) train the model 39 | """ 40 | args = get_arguments() 41 | logger.info('set seed') 42 | torch.manual_seed(9) 43 | deepspeed.runtime.utils.set_random_seed(9) 44 | 45 | logger.info('initialize NCCL & CUDA') 46 | deepspeed.init_distributed(dist_backend='nccl') 47 | args.local_rank = int(os.environ['LOCAL_RANK']) 48 | torch.cuda.set_device(args.local_rank) # local rank passed from distributed launcher 49 | 50 | config = ModelConfig(config_path=args.config).get_config() 51 | 52 | tokenizer = BertTokenizer(vocab_file=config.vocab_path, do_lower_case=False) 53 | 54 | logger.info('load gptx dataset') 55 | # dataset = GPTXDatasetV2(tokenizer, config.max_seq_len, config.data_path) 56 | dataset = gptx_datset(config, tokenizer, GPTXDatasetV2) 57 | 58 | wandb.init(project="rezero_sparsetopk_gpt") 59 | 60 | train_dataloader, eval_dataloader = build_dataloaders(config, dataset, train_test_split=0.1) 61 | logger.info(f'train data length: {len(train_dataloader)}') 62 | logger.info(f'eval data length : {len(eval_dataloader)}') 63 | 64 | config.max_train_step = len(train_dataloader) * config.epoch 65 | config.max_eval_step = len(eval_dataloader) 66 | 67 | logger.info('set GPTX model, optimizer, scheduler') 68 | model, optimizer, lr_scheduler = setup_model_and_optimizer(config) 69 | 70 | logger.info('deepspeed initialize') 71 | model,optimizer, _, lr_scheduler = deepspeed.initialize( 72 | model=model, 73 | optimizer=optimizer, 74 | args=args, 75 | lr_scheduler=lr_scheduler, 76 | dist_init_required=False) 77 | 78 | logger.info('start training') 79 | train(config=config, 80 | model=model, 81 | train_dataloader=cycle(train_dataloader)) 82 | 83 | evaluate(config, model, eval_dataloader=cycle(eval_dataloader)) 84 | 85 | def cross_entropy(lm_logits, labels): 86 | loss = None 87 | if labels is not None: 88 | # Shift so that tokens < n predict n 89 | shift_logits = lm_logits[..., :-1, :].contiguous() 90 | shift_labels = labels[..., 1:].contiguous() 91 | 92 | # Flatten the tokens 93 | loss_fn = CrossEntropyLoss() 94 | loss = loss_fn(shift_logits.view(-1, shift_logits.size(-1)), shift_labels.view(-1)) 95 | 96 | return loss 97 | def train(config, 98 | model, 99 | train_dataloader): 100 | 101 | # Set train mode 102 | model.train() 103 | 104 | logger.info('start pretrainig iteration') 105 | 106 | for i in range(config.max_train_step): 107 | loss = model.train_batch(data_iter=train_dataloader) 108 | wandb.log({'train': {'loss': loss.item(), 'perplexity': torch.exp(loss)}}) 109 | 110 | train_result = {"loss": loss.item(), "ppl": torch.exp(loss)} 111 | 112 | return train_result 113 | 114 | def evaluate(config, model, eval_dataloader): 115 | model.eval() 116 | 117 | with torch.no_grad(): 118 | for _ in range(config.max_eval_step): 119 | loss = model.eval_batch(data_iter=eval_dataloader) 120 | wandb.log({'eval': {'loss': loss.item(), 'perplexity': torch.exp(loss)}}) 121 | 122 | eval_result = {"loss": loss.item(), "ppl": torch.exp(loss)} 123 | model.train() 124 | return eval_result 125 | 126 | def setup_model_and_optimizer(config): 127 | """""" 128 | model = get_model(config) 129 | optimizer, model_params = get_optimizer(config, model) 130 | lr_scheduler = get_learning_rate_scheduler(optimizer=optimizer, config=config) 131 | 132 | return model, optimizer, lr_scheduler 133 | 134 | def get_model(config): 135 | model = ReZroSparseTopkGPTPipe(vocab_size= config.vocab_size, 136 | dim = config.dim, 137 | depth = config.depth, 138 | n_head= config.n_head, 139 | max_seq_len= config.max_seq_len) 140 | model = model.to_layer() 141 | model = PipelineModule(layers=model, 142 | loss_fn=cross_entropy, 143 | num_stages=config.num_stages) 144 | return model 145 | 146 | def get_model_params( model): 147 | named_parameter = list(model.named_parameters()) 148 | no_decay = ['bias', 'LayerNorm'] 149 | 150 | optimizer_grouped_parameters = [ 151 | {'params': [p for n, p in named_parameter if not any(nd in n for nd in no_decay)], 152 | 'weight_decay': 0.01}, 153 | {'params': [p for n, p in named_parameter if any(nd in n for nd in no_decay)], 'weight_decay': 0.0} 154 | ] 155 | return optimizer_grouped_parameters 156 | 157 | def get_optimizer(config, model): 158 | model_params = get_model_params(model) 159 | if config.optimizer['type']=='cpu_adam': 160 | from deepspeed.ops.adam import DeepSpeedCPUAdam 161 | optimizer = DeepSpeedCPUAdam(model_params, 162 | **config.optimizer['params']) 163 | elif config.optimizer['type']=='adam': 164 | from deepspeed.ops.adam import FusedAdam as Adam 165 | optimizer = Adam(model_params, 166 | **config.optimizer['params']) 167 | return optimizer,model_params 168 | 169 | def get_learning_rate_scheduler(optimizer, config): 170 | num_iter = config.max_train_step 171 | lr_scheduler = torch.optim.lr_scheduler.OneCycleLR(optimizer=optimizer, 172 | max_lr=config.optimizer['params']['lr'], 173 | total_steps=num_iter, 174 | pct_start=config.warmup_iter, 175 | anneal_strategy='cos'# or 'linear' 176 | ) 177 | return lr_scheduler 178 | 179 | def build_dataloaders(config, dataset, train_test_split=0.1, train_shuffle=True, eval_shuffle=True): 180 | dataset_len = len(dataset) 181 | eval_len = int(dataset_len * train_test_split) 182 | train_len = dataset_len - eval_len 183 | train_dataset, eval_dataset = random_split(dataset, (train_len, eval_len)) 184 | train_loader = DataLoader(train_dataset, batch_size=config.batch_size, shuffle=train_shuffle) 185 | eval_loader = DataLoader(eval_dataset, batch_size=config.batch_size, shuffle=eval_shuffle) 186 | logging.info(f'''train_dataloader size: {len(train_loader.dataset)} | shuffle: {train_shuffle} 187 | eval_dataloader size: {len(eval_loader.dataset)} | shuffle: {eval_shuffle}''') 188 | 189 | # return iter(train_loader), iter(eval_loader) 190 | 191 | return train_loader, eval_loader 192 | 193 | def gptx_datset(config, tokenizer, dataset_obj): 194 | cache_data_path = f'{config.cache_path}/{config.model_name}.pickle' 195 | cache_dir_path= os.path.dirname(cache_data_path) 196 | 197 | if os.path.exists(cache_data_path): # 캐시 데이터가 존재하는 경우 198 | dataset = torch.load(cache_data_path) 199 | return dataset 200 | else: # 캐시 데이터가 없는 경우 201 | if not os.path.exists(cache_dir_path): 202 | os.makedirs(cache_dir_path) # 캐시 디렉토리 경로 생성 203 | 204 | dataset = dataset_obj(tokenizer, config.max_seq_len, config.data_path) 205 | torch.save(dataset, cache_data_path) # 데이터 저장 206 | 207 | return dataset 208 | 209 | def get_arguments(): 210 | parser = get_argument_parser() 211 | # Include DeepSpeed configuration arguments 212 | parser = deepspeed.add_config_arguments(parser) 213 | args = parser.parse_args() 214 | # no cuda mode is not supported 215 | args.no_cuda = False 216 | 217 | return args 218 | 219 | if __name__ == '__main__': 220 | pretrain() 221 | -------------------------------------------------------------------------------- /train_pl/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "vocab_path" : "../data/vocab-v1.txt", 3 | "data_path" :"../data/train/" , 4 | "checkpoint_path" : "../checkpoints", 5 | "model_name": "gptx", 6 | "dim": 2560, 7 | "depth": 8, 8 | "n_head": 32, 9 | "max_seq_len" : 1024, 10 | "dropout_prob": 0.3, 11 | "batch_size" : 2, 12 | "epochs" : 10, 13 | "ckpt_steps" : 1000, 14 | "gradient_accumulation_steps" : 512, 15 | "gpu": 2, 16 | "deepspeed_plugin":"deepspeed_stage_2_offload", 17 | "precision": "16" 18 | } 19 | -------------------------------------------------------------------------------- /train_pl/config_small.json: -------------------------------------------------------------------------------- 1 | { 2 | "vocab_path" : "./data/vocab-v1.txt", 3 | "data_path" :"./data/train/" , 4 | "checkpoint_path" : "./checkpoints", 5 | "log_dir": "./logs", 6 | "model_name": "reformer-gpt3", 7 | "dim": 1536, 8 | "depth": 16, 9 | "n_head": 96, 10 | "max_seq_len" : 1024, 11 | "batch_size" : 4, 12 | "epochs" : 10, 13 | "log_steps" : 1, 14 | "ckpt_steps" : 10000, 15 | "gradient_accumulation_steps" : 256, 16 | "fp16": false, 17 | "fp16_opt_level": "O2", 18 | "device":"cuda" 19 | } 20 | -------------------------------------------------------------------------------- /train_pl/run_pretraining.py: -------------------------------------------------------------------------------- 1 | import os 2 | import sys 3 | sys.path.append('../') 4 | import torch 5 | import pytorch_lightning as pl 6 | from pytorch_lightning.callbacks import ModelCheckpoint 7 | from pytorch_lightning.loggers import TensorBoardLogger 8 | from common.arg import ModelConfig 9 | from common.dataset import GPTXDatasetV2 10 | from model.transformer import LitGPT2 11 | from transformers import BertTokenizer 12 | from torch.utils.data import random_split, DataLoader 13 | from pytorch_lightning.loggers import WandbLogger 14 | 15 | 16 | def build_dataloader(dataset, batch_size, train_rate=0.8,shuffle=True): 17 | train_data_len = int(len(dataset) * train_rate) 18 | valid_data_len = len(dataset) - train_data_len 19 | 20 | train_data, valid_data = random_split(dataset, (train_data_len, valid_data_len)) 21 | 22 | train_dataloader = DataLoader(train_data, batch_size=batch_size, shuffle=shuffle) 23 | valid_dataloader = DataLoader(valid_data, batch_size=batch_size, shuffle=shuffle) 24 | 25 | return train_dataloader, valid_dataloader 26 | 27 | def gptx_dataset(config, tokenizer): 28 | cache_data_path = f'{config.checkpoint_path}/{config.model_name}.pickle' 29 | cache_dir_path= os.path.dirname(cache_data_path) 30 | 31 | if os.path.exists(cache_data_path): # 캐시 데이터가 존재하는 경우 32 | dataset = torch.load(cache_data_path) 33 | return dataset 34 | else: # 캐시 데이터가 없는 경우 35 | if not os.path.exists(cache_dir_path): 36 | os.makedirs(cache_dir_path) # 캐시 디렉토리 경로 생성 37 | 38 | dataset = GPTXDatasetV2(tokenizer, config.max_seq_len, config.data_path) 39 | torch.save(dataset, cache_data_path) # 데이터 저장 40 | 41 | return dataset 42 | 43 | if __name__=='__main__': 44 | torch.manual_seed(9) 45 | base_path = '..' 46 | 47 | # Config 48 | config_path = f'{base_path}/config.json' 49 | config = ModelConfig(config_path=config_path).get_config() 50 | 51 | # Tokenizer 52 | tokenizer = BertTokenizer(vocab_file=config.vocab_path, do_lower_case=False) 53 | 54 | # Dataset 55 | dataset = gptx_dataset(config, tokenizer) 56 | train_dataloader, valid_dataloader = build_dataloader(dataset, config.batch_size,0.9) 57 | 58 | model = LitGPT2( 59 | vocab_size=tokenizer.vocab_size, 60 | dim=config.dim, 61 | depth=config.depth, 62 | head_num=config.n_head, 63 | max_seq_len=config.max_seq_len, # AxialPositionalEmbedding을 위한 (79,64) 값 and max_len/(bucket_size*2) == 0 이어야한다. 현재 bucket_size = 64 64 | ) 65 | 66 | checkpoint_callback = ModelCheckpoint( 67 | dirpath=config.checkpoint_path, 68 | filename=f"{config.model_name}-"+"{epoch}-{step}", 69 | every_n_train_steps=config.ckpt_steps, 70 | # save_top_k = 2 71 | ) 72 | 73 | # logger 74 | # logger = TensorBoardLogger('tb_logs', name=config.model_name) 75 | logger = WandbLogger(project="gpt-x") 76 | 77 | # Trainer 78 | trainer = pl.Trainer(gpus=config.gpu, 79 | plugins=config.deepspeed_plugin, 80 | precision=config.precision, 81 | logger=logger, 82 | # accumulate_grad_batches=config.gradient_accumulation_steps, 83 | max_epochs=config.epochs, 84 | callbacks=[checkpoint_callback] 85 | ) 86 | 87 | trainer.fit(model,train_dataloader=train_dataloader,val_dataloaders=valid_dataloader) -------------------------------------------------------------------------------- /train_pl/run_pretraining_rezero.py: -------------------------------------------------------------------------------- 1 | import os 2 | import sys 3 | sys.path.append('../') 4 | import torch 5 | import pytorch_lightning as pl 6 | from pytorch_lightning.callbacks import ModelCheckpoint 7 | from pytorch_lightning.loggers import TensorBoardLogger 8 | from common.arg import ModelConfig 9 | from common.dataset import GPTXDatasetV2 10 | from model.transformer import LitGPT2 11 | from transformers import BertTokenizer 12 | from torch.utils.data import random_split, DataLoader 13 | from pytorch_lightning.loggers import WandbLogger 14 | 15 | 16 | def build_dataloader(dataset, batch_size, train_rate=0.8,shuffle=True): 17 | train_data_len = int(len(dataset) * train_rate) 18 | valid_data_len = len(dataset) - train_data_len 19 | 20 | train_data, valid_data = random_split(dataset, (train_data_len, valid_data_len)) 21 | 22 | train_dataloader = DataLoader(train_data, batch_size=batch_size, shuffle=shuffle) 23 | valid_dataloader = DataLoader(valid_data, batch_size=batch_size, shuffle=shuffle) 24 | 25 | return train_dataloader, valid_dataloader 26 | 27 | def gptx_dataset(config, tokenizer): 28 | cache_data_path = f'{config.checkpoint_path}/{config.model_name}.pickle' 29 | cache_dir_path= os.path.dirname(cache_data_path) 30 | 31 | if os.path.exists(cache_data_path): # 캐시 데이터가 존재하는 경우 32 | dataset = torch.load(cache_data_path) 33 | return dataset 34 | else: # 캐시 데이터가 없는 경우 35 | if not os.path.exists(cache_dir_path): 36 | os.makedirs(cache_dir_path) # 캐시 디렉토리 경로 생성 37 | 38 | dataset = GPTXDatasetV2(tokenizer, config.max_seq_len, config.data_path) 39 | torch.save(dataset, cache_data_path) # 데이터 저장 40 | 41 | return dataset 42 | 43 | if __name__=='__main__': 44 | torch.manual_seed(9) 45 | base_path = '.' 46 | 47 | # Config 48 | config_path = f'{base_path}/config_gpt2.json' 49 | config = ModelConfig(config_path=config_path).get_config() 50 | 51 | # Tokenizer 52 | tokenizer = BertTokenizer(vocab_file=config.vocab_path, do_lower_case=False) 53 | 54 | # Dataset 55 | dataset = gptx_dataset(config, tokenizer) 56 | train_dataloader, valid_dataloader = build_dataloader(dataset, config.batch_size,0.9) 57 | 58 | model = LitGPT2( 59 | vocab_size=tokenizer.vocab_size, 60 | dim=config.dim, 61 | depth=config.depth, 62 | head_num=config.n_head, 63 | max_seq_len=config.max_seq_len, # AxialPositionalEmbedding을 위한 (79,64) 값 and max_len/(bucket_size*2) == 0 이어야한다. 현재 bucket_size = 64 64 | ) 65 | 66 | checkpoint_callback = ModelCheckpoint( 67 | dirpath=config.checkpoint_path, 68 | filename=f"{config.model_name}-"+"{epoch}-{step}", 69 | every_n_train_steps=config.ckpt_steps, 70 | # save_top_k = 2 71 | ) 72 | 73 | # logger 74 | # logger = TensorBoardLogger('tb_logs', name=config.model_name) 75 | logger = WandbLogger(project="gpt-rezero") 76 | 77 | # Trainer 78 | trainer = pl.Trainer(gpus=config.gpu, 79 | plugins=config.deepspeed_plugin, 80 | precision=config.precision, 81 | logger=logger, 82 | # accumulate_grad_batches=config.gradient_accumulation_steps, 83 | max_epochs=config.epochs, 84 | callbacks=[checkpoint_callback] 85 | ) 86 | 87 | trainer.fit(model,train_dataloader=train_dataloader,val_dataloaders=valid_dataloader) 88 | -------------------------------------------------------------------------------- /train_pl/run_pretraining_rezero_sparsetopk.py: -------------------------------------------------------------------------------- 1 | import os 2 | import sys 3 | sys.path.append('../') 4 | import torch 5 | import pytorch_lightning as pl 6 | from pytorch_lightning.callbacks import ModelCheckpoint 7 | from pytorch_lightning.loggers import TensorBoardLogger 8 | from common.arg import ModelConfig 9 | from common.dataset import GPTXDatasetV2 10 | from model.transformer import LitGPT2 11 | from transformers import BertTokenizer 12 | from torch.utils.data import random_split, DataLoader 13 | from pytorch_lightning.loggers import WandbLogger 14 | 15 | 16 | def build_dataloader(dataset, batch_size, train_rate=0.8,shuffle=True): 17 | train_data_len = int(len(dataset) * train_rate) 18 | valid_data_len = len(dataset) - train_data_len 19 | 20 | train_data, valid_data = random_split(dataset, (train_data_len, valid_data_len)) 21 | 22 | train_dataloader = DataLoader(train_data, batch_size=batch_size, shuffle=shuffle) 23 | valid_dataloader = DataLoader(valid_data, batch_size=batch_size, shuffle=shuffle) 24 | 25 | return train_dataloader, valid_dataloader 26 | 27 | def gptx_dataset(config, tokenizer): 28 | cache_data_path = f'{config.checkpoint_path}/{config.model_name}.pickle' 29 | cache_dir_path= os.path.dirname(cache_data_path) 30 | 31 | if os.path.exists(cache_data_path): # 캐시 데이터가 존재하는 경우 32 | dataset = torch.load(cache_data_path) 33 | return dataset 34 | else: # 캐시 데이터가 없는 경우 35 | if not os.path.exists(cache_dir_path): 36 | os.makedirs(cache_dir_path) # 캐시 디렉토리 경로 생성 37 | 38 | dataset = GPTXDatasetV2(tokenizer, config.max_seq_len, config.data_path) 39 | torch.save(dataset, cache_data_path) # 데이터 저장 40 | 41 | return dataset 42 | 43 | if __name__=='__main__': 44 | torch.manual_seed(9) 45 | base_path = '.' 46 | 47 | # Config 48 | config_path = f'{base_path}/config_gpt2.json' 49 | config = ModelConfig(config_path=config_path).get_config() 50 | 51 | # Tokenizer 52 | tokenizer = BertTokenizer(vocab_file=config.vocab_path, do_lower_case=False) 53 | 54 | # Dataset 55 | dataset = gptx_dataset(config, tokenizer) 56 | train_dataloader, valid_dataloader = build_dataloader(dataset, config.batch_size,0.9) 57 | 58 | model = LitGPT2( 59 | vocab_size=tokenizer.vocab_size, 60 | dim=config.dim, 61 | depth=config.depth, 62 | head_num=config.n_head, 63 | max_seq_len=config.max_seq_len, # AxialPositionalEmbedding을 위한 (79,64) 값 and max_len/(bucket_size*2) == 0 이어야한다. 현재 bucket_size = 64 64 | ) 65 | 66 | checkpoint_callback = ModelCheckpoint( 67 | dirpath=config.checkpoint_path, 68 | filename=f"{config.model_name}-"+"{epoch}-{step}", 69 | every_n_train_steps=config.ckpt_steps, 70 | # save_top_k = 2 71 | ) 72 | 73 | # logger 74 | # logger = TensorBoardLogger('tb_logs', name=config.model_name) 75 | logger = WandbLogger(project="gpt-rezero-sparsetopk") 76 | 77 | # Trainer 78 | trainer = pl.Trainer(gpus=config.gpu, 79 | plugins=config.deepspeed_plugin, 80 | precision=config.precision, 81 | logger=logger, 82 | # accumulate_grad_batches=config.gradient_accumulation_steps, 83 | max_epochs=config.epochs, 84 | callbacks=[checkpoint_callback] 85 | ) 86 | 87 | trainer.fit(model,train_dataloader=train_dataloader,val_dataloaders=valid_dataloader) 88 | --------------------------------------------------------------------------------