Spaces:
Sleeping
Sleeping
Download myapp/step2_semantic.py from sungho7373/FakeAD-Detector: direct link, hf CLI and curl.
- Browser
- Download file 6.06 kB
-
https://huggingface.co/spaces/sungho7373/FakeAD-Detector/resolve/main/myapp/step2_semantic.py
- Command line
-
hf download hf://spaces/sungho7373/FakeAD-Detector/myapp/step2_semantic.py
-
curl -L -o step2_semantic.py https://huggingface.co/spaces/sungho7373/FakeAD-Detector/resolve/main/myapp/step2_semantic.py
6.06 kB
| import torch | |
| import torch.nn.functional as F | |
| from transformers import AutoTokenizer, AutoModelForSequenceClassification | |
| import gc | |
| class SemanticAnalyzer: | |
| def __init__(self): | |
| print("๐ง [Step 2] ์๋ฏธ๋ก ์ ๋ฅ๋ฌ๋ ๋ถ์๊ธฐ(KoELECTRA)๋ฅผ ๋ก๋ํฉ๋๋ค...") | |
| # M1 Max GPU(MPS) ์ธํ | |
| self.device = torch.device("mps" if torch.backends.mps.is_available() else "cpu") | |
| # ๊ฐ๋ณ๊ณ ์ฑ๋ฅ์ด ๋ฐ์ด๋ KoELECTRA ๋ชจ๋ธ ๋ก๋ | |
| self.model_name = "monologg/koelectra-base-v3-discriminator" | |
| self.tokenizer = AutoTokenizer.from_pretrained(self.model_name) | |
| # ๐ ํต์ฌ: output_hidden_states=True ์ต์ ์ ์ผ์ผ | |
| # ๋ถ๋ฅ Logit๊ณผ ์ฝ์ฌ์ธ ์ ์ฌ๋์ฉ Vector๋ฅผ ํ ๋ฒ์ ์ฐ์ฐ์ผ๋ก ๋ ๋ค ๋ฝ์๋ผ ์ ์์ต๋๋ค! | |
| self.model = AutoModelForSequenceClassification.from_pretrained( | |
| self.model_name, | |
| num_labels=2, # 0: ์ ์, 1: ๊ณผ๋๊ด๊ณ | |
| output_hidden_states=True | |
| ).to(self.device) | |
| self.model.eval() # ์ถ๋ก ๋ชจ๋ ์ ํ | |
| # [๋ฒกํฐ A ๊ตฌ์ถ] ๊ธฐ์กด์ ์ ๋ฐ๋ ํ์๊ด๊ณ ๋ ํผ๋ฐ์ค ๋ฌธ์ฅ๋ค (์์) | |
| self.reference_bad_texts = [ | |
| "๋จ ์ผ์ฃผ์ผ ๋ง์ ์ง๋ฐฉ์ด 100% ๋ถํด๋๋ ๊ธฐ์ ์ ํฌ๋ฆผ", | |
| "์์ฝ์ฒ์์ ์ธ์ฆํ ๋ง๋ณํต์น์ฝ, ์์ธํฌ ์๋ฒฝ ์ ๊ฑฐ", | |
| "์ด๊ฒ๋ง ๋จน์ผ๋ฉด ๋ ์๊ฐ ๋ฐฐ์ถ๋๊ณ ์ธํฌ๊ฐ ์ฆ๊ฐ ์ฌ์๋ฉ๋๋ค", | |
| "์์ฌ๋ค์ด ๋ฌด์กฐ๊ฑด ์ถ์ฒํ๋ ๋ถ์์ฉ ์๋ ์์น์ " | |
| ] | |
| print(" -> ๋ ํผ๋ฐ์ค ํ์๊ด๊ณ ๋ฌธ์ฅ๋ค์ ๋ฒกํฐ(Vector) ๊ณต๊ฐ์ ๋ฐฐ์น ์ค...") | |
| self.reference_embeddings = self._get_embeddings(self.reference_bad_texts) | |
| def clear_memory(self): | |
| """๋ฉ๋ชจ๋ฆฌ ๋์ ๋ฐฉ์ง์ฉ ๊ฐ๋น์ง ์ปฌ๋ ์ """ | |
| gc.collect() | |
| if torch.backends.mps.is_available(): | |
| torch.mps.empty_cache() | |
| def _get_embeddings(self, texts): | |
| """ํ ์คํธ ๋ฆฌ์คํธ๋ฅผ ์ ๋ ฅ๋ฐ์ ๋ฌธ์ฅ ์๋ฒ ๋ฉ ๋ฒกํฐ๋ฅผ ๋ฐํํฉ๋๋ค.""" | |
| inputs = self.tokenizer(texts, padding=True, truncation=True, max_length=512, return_tensors="pt").to(self.device) | |
| with torch.no_grad(): | |
| outputs = self.model(**inputs) | |
| # ๋ง์ง๋ง ๋ ์ด์ด์ hidden states์์ [CLS] ํ ํฐ(์ธ๋ฑ์ค 0)์ ๋ฒกํฐ๋ฅผ ๋ฌธ์ฅ ๋ํ ๋ฒกํฐ๋ก ์ฌ์ฉ | |
| sentence_embeddings = outputs.hidden_states[-1][:, 0, :] | |
| return sentence_embeddings | |
| def calculate_x2_score(self, text): | |
| if not text or len(text.strip()) < 5: | |
| return 0.0 | |
| print("\n๐ง [Step 2] ๋ฅ๋ฌ๋ ๋ฌธ๋งฅ ๋ฐ ์ ์ฌ๋(Semantic) ๋ถ์ ์์...") | |
| # ๋๋ฌด ๊ธด ํ ์คํธ๋ PLM ํ๊ณ(512ํ ํฐ)์ ๊ฑธ๋ฆฌ๋ฏ๋ก ์๋ผ์ ์ ๋ ฅ | |
| inputs = self.tokenizer(text, return_tensors="pt", truncation=True, max_length=512).to(self.device) | |
| with torch.no_grad(): # ์ญ์ ํ(ํ์ต) ์ฐ์ฐ์ ๊บผ์ M1 ๋ฉ๋ชจ๋ฆฌ ์ ์ฝ | |
| outputs = self.model(**inputs) | |
| # ========================================================= | |
| # [์์ 1] ๋ถ๋ฅ ํ๋ฅ (Softmax) : X2 | |
| # ========================================================= | |
| logits = outputs.logits # ๋ชจ๋ธ์ ๋ ๊ฒ ์ถ๋ ฅ๊ฐ (z) | |
| probs = F.softmax(logits, dim=-1) # Softmax ์ ์ฉ: e^z / sum(e^z) | |
| # ๋ผ๋ฒจ 1(๊ณผ๋๊ด๊ณ )์ ํด๋นํ๋ ํ๋ฅ ๊ฐ (0.0 ~ 1.0) | |
| prob_fake = probs[0][1].item() | |
| # ========================================================= | |
| # [์์ 2] ์๋ฏธ๋ก ์ ์ ์ฌ๋ (Cosine Similarity) | |
| # ========================================================= | |
| # ํ์ฌ ๊ฒ์ฌ ์ค์ธ ํ ์คํธ์ ๋ฒกํฐ B ์ถ์ถ | |
| current_embedding = outputs.hidden_states[-1][:, 0, :] | |
| # ๋ ํผ๋ฐ์ค ๋ฒกํฐ A๋ค๊ณผ ๋ฒกํฐ B์ ์ ์ฌ๋ ๊ณ์ฐ: (A * B) / (|A| * |B|) | |
| similarities = F.cosine_similarity(current_embedding, self.reference_embeddings) | |
| # ๊ฐ์ฅ ๋ฌธ๋งฅ์ด ๋น์ทํ๋ค๊ณ ํ์ ๋ ๋ ํผ๋ฐ์ค์์ ์ต๊ณ ์ ์ฌ๋ ์ ์ | |
| max_sim = torch.max(similarities).item() | |
| # ๋ถ์์ด ๋๋๋ฉด ์ฆ์ VRAM ๋ฐํ | |
| del inputs, outputs, logits, probs, current_embedding, similarities | |
| self.clear_memory() | |
| # ========================================================= | |
| # ์ต์ข X2 ์ค์ฝ์ด ์ฐ์ถ (๋ถ๋ฅ ํ๋ฅ + ์ ์ฌ๋ ์์๋ธ) | |
| # ========================================================= | |
| # ๋ถ๋ฅ๊ธฐ ํ๋ฅ ์ 100์ ๋ง์ ์ผ๋ก ๋ณํ | |
| classification_score = prob_fake * 100 | |
| # ์ฝ์ฌ์ธ ์ ์ฌ๋๋ฅผ 100์ ๋ง์ ์ผ๋ก ๋ณํ (์ ์ฌ๋๊ฐ 0 ์ดํ๋ฉด 0์ ์ฒ๋ฆฌ) | |
| similarity_score = max(max_sim, 0) * 100 | |
| # ๐ก [์ค๋ฌด ํ] ํผํฉ ๊ฐ์ค์น ์ ์ฉ | |
| # ํ์ฌ KoELECTRA ๋ชจ๋ธ์ '๊ณผ๋๊ด๊ณ ์ ์ฉ'์ผ๋ก ํ์ธํ๋ ๋์ง ์์ ์ฉ์ผ ์ํ์ ๋๋ค. | |
| # ๋ฐ๋ผ์ Softmax ๋ถ๋ฅ ํ๋ฅ ์ ๋๋ค์ ๊ฐ๊น๊ณ , ์ฝ์ฌ์ธ ์ ์ฌ๋๊ฐ ํจ์ฌ ์ ํํฉ๋๋ค. | |
| # ์ ์ฌ๋ ์ ์์ 80%, ๋ถ๋ฅ ์ ์์ 20% ๊ฐ์ค์น๋ฅผ ์ฃผ์ด ์ต์ข ์ ์๋ฅผ ๋ง๋ญ๋๋ค. | |
| x2_score = (similarity_score * 0.8) + (classification_score * 0.2) | |
| print(f" -> ๐ ๋ชจ๋ธ ๋ถ๋ฅ ํ๋ฅ (Softmax): {prob_fake*100:.1f}%") | |
| print(f" -> ๐ ์ต๋ ๋ฌธ๋งฅ ์ ์ฌ๋ (Cosine Sim): {max_sim*100:.1f}%") | |
| print(f"๐ ์ต์ข X2 ์ ์ (0~100): {x2_score:.2f}์ ") | |
| return x2_score | |
| # ========================================== | |
| # ๋จ๋ ํ ์คํธ ์ฝ๋ | |
| # ========================================== | |
| if __name__ == "__main__": | |
| analyzer = SemanticAnalyzer() | |
| # ๋ ํผ๋ฐ์ค("๋จ ์ผ์ฃผ์ผ ๋ง์...")์ ์๋ฏธ๊ฐ ์ ์ฌํ ๋ฌธ์ฅ ํ ์คํธ | |
| test_text = "๋จ 7์ผ๋ง ํฌ์ํ์ธ์! ์ง๋ฐฉ์ด ์์ ํ ํ๊ดด๋๋ ๋๋ผ์ด ๋ง๋ฒ์ ๊ฒช๊ฒ ๋ฉ๋๋ค." | |
| analyzer.calculate_x2_score(test_text) |