728x90
개념과 포지셔닝
- n-그램이란?
- 텍스트·음성·유전체 등에서 연속된 n개의 단위(기호) 묶음입니다.
- 단위: 문자(char), 음절/자모, 단어(word), 음소(phoneme), 염기쌍(base) 등.
- 왜 지금 n-그램인가?
- “원하는 결과를 정확히 지시하고, 반복 피드백으로 품질을 올리는 구조”가 중요합니다.
- n-그램은 이 구조에서 (a) 결과 평가 지표, (b) 데이터 전처리/색인, (c) 탐지 피처로 다용도 핵심 블록이 됩니다.
- 선택 가이드(한국어 포함)
- 문자 3–5그램: URL/도메인/경로/명령어/로그 문자열·오타/띄어쓰기 변동에 강함.
- 단어 1–2그램(형태소 기반 권장): 보고서/메일/공지처럼 주제·문맥이 중요할 때.
- 혼합: 실무에선 문자 n-그램 ⊕ 단어 n-그램 ⊕ 통계 피처(길이·엔트로피 등) 결합이 강력.
활용 아키텍처(프레임 ⇨ n-그램)
- 명확한 지시(프롬프트) → 데이터/목표 정의
- “피싱 메일 자동 분류”, “명령어 이상탐지”, “오타 허용 검색”, “AI 티 검출/감추기”처럼 업무 목적을 1문장으로 고정.
- 템플릿(표준화) → n-그램 설계 표준
- 토큰 단위,
ngram_range
, 최소/최대 빈도(min_df/max_df
), 가중치(TF-IDF/확률), 스무딩 등 팀 표준 YAML로 고정.
- 피드백 루프 → 지표·대시보드
- 분류: F1/PR-AUC, 검색: nDCG/MRR, 이상탐지: 퍼플렉서티, 운영: 드리프트/오탐 지표.
- 월별 재학습/사전 갱신·룰 조정으로 지속 개선.
- 결과 평가 → n-그램 기반 품질/스타일 검수
- “AI 티 제거”는 n-그램 반복률/희귀도/개인 문체 프로파일 비교로 수치화 → 편집 가이드 자동 제안.
대표 시나리오 총람
- 보고서/메일 품질 관리(“AI 티” 줄이기)
- 개인 문체 코퍼스의 단어/문자 n-그램 분포와 초안 비교 → 반복/상투구 제거, 구문 다양화 제안.
- 피싱/스팸 분류
- 본문(단어 1–2그램 TF-IDF) ⊕ 제목/URL(문자 3–5그램) → 선형 SVM/로지스틱.
- DGA 및 수상한 도메인 탐지
- 문자 3–5그램 TF-IDF + 엔트로피/숫자비율 → 로지스틱/트리 앙상블.
- 명령어·로그 이상탐지(언어모델)
- 문자 n-그램 언어모델의 퍼플렉서티로 낯선 옵션/인코딩 페이로드 탐지.
- 유사 페이지/문서 탐지(변종/표절)
- 고정 길이 n-그램 셰글링 + MinHash/LSH로 빠른 근사 유사도.
- 검색/오타 허용/자동완성(Elasticsearch/OpenSearch)
- 색인 시 n-그램, 검색 시 표준 분석기 → 부분일치·오타 회복.
300x250
실무 예시 (코드/설정)
1. “AI 티” 검수: 문체 프로파일 비교(파이썬)
# pip install scikit-learn nltk
from sklearn.feature_extraction.text import TfidfVectorizer
import numpy as np
user_samples = [
"저는 요약 시 결론을 먼저 제시하고, 근거를 간단히 나열합니다.",
"정책 변경 시 영향 범위를 목록화하고 예외를 별도로 명시합니다."
]
draft = "본 보고서는 전반적으로 양호합니다. 결론적으로 보안 지표는 상승했습니다. ..." # AI 초안
vec = TfidfVectorizer(analyzer="word", ngram_range=(1,2), min_df=1, max_df=0.95)
X = vec.fit_transform(user_samples + [draft]).toarray()
user_profile = X[:-1].mean(axis=0)
draft_vec = X[-1]
# 상위 특징 n-그램 비교
terms = np.array(vec.get_feature_names_out())
diff = draft_vec - user_profile
top_over = terms[np.argsort(diff)][-10:] # 초안에서 과도한 n-그램
top_under = terms[np.argsort(-diff)][-10:] # 사용자 문체 대비 부족한 n-그램
print("과도한 반복/상투 표현 후보:", list(top_over))
print("개인 문체 반영이 부족한 표현:", list(top_under))
→ 활용: “과도한 표현”은 제거/치환, “부족한 표현”은 개인 어휘/전문용어로 보강하도록 제안.
2. 피싱/스팸 분류(단어 1–2그램 + 문자 3–5그램 결합)
# pip install scikit-learn
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.pipeline import FeatureUnion, Pipeline
from sklearn.svm import LinearSVC
from sklearn.metrics import classification_report
subjects = ["긴급: 비밀번호 재설정", "분기 보안 점검 결과", "급여 명세 안내"]
bodies = [
"계정 확인 필요. 아래 링크 클릭.",
"ISMS 점검 결과와 개선계획 첨부",
"사내망에서만 확인 바랍니다."
]
y = [1,0,0] # 1=피싱 의심
word_vec = TfidfVectorizer(analyzer="word", ngram_range=(1,2), min_df=1)
char_vec = TfidfVectorizer(analyzer="char", ngram_range=(3,5), min_df=1)
X_text = [s + " " + b for s,b in zip(subjects, bodies)]
clf = Pipeline([
("feat", FeatureUnion([("w", word_vec), ("c", char_vec)])),
("svm", LinearSVC())
])
clf.fit(X_text, y)
print(clf.predict(["[경고] 계정 이상 활동 확인, 즉시 링크 접속"]))
팁: 발신 도메인 SLD/경로 토큰도 문자 n-그램으로 추가 → 변종에 강해집니다.
3. DGA 탐지(문자 3–5그램 + 부가 피처)
# pip install scikit-learn numpy
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.linear_model import LogisticRegression
from sklearn.pipeline import Pipeline
import numpy as np
domains = ["login-google.com", "asdkjas9qwe.biz", "intra.corp.local", "xj3kq9a.top"]
y = [0,1,0,1]
pipe = Pipeline([
("vec", TfidfVectorizer(analyzer="char", ngram_range=(3,5), min_df=1)),
("clf", LogisticRegression(max_iter=300))
])
pipe.fit(domains, y)
print(pipe.predict_proba(["acc-update-secure.com"])[:,1]) # DGA 점수(확률)
운영 팁: 점수 + 엔트로피/자모비율/숫자비율/TLD 신뢰도/WHOIS 정보 룰 결합 → 오탐 억제.
4. 명령어 이상탐지(문자 n-그램 언어모델 → 퍼플렉서티)
from collections import Counter
import math
def train_char_lm(cmds, n=3, alpha=0.5):
ngram, ctx = Counter(), Counter()
V = set()
for s in cmds:
s = "^" + s + "$" # 문장 경계
for i in range(len(s)-n+1):
g = s[i:i+n]; c = g[:-1]
ngram[g]+=1; ctx[c]+=1
V.update(s)
V = len(V)
def perplexity(s):
s = "^" + s + "$"
logp, N = 0.0, 0
for i in range(len(s)-n+1):
g = s[i:i+n]; c = g[:-1]
p = (ngram[g]+alpha)/(ctx[c]+alpha*V)
logp += -math.log(p); N += 1
return math.exp(logp/max(N,1))
return perplexity
benign = ["ls -la","cat /etc/passwd","ps aux","grep -i error /var/log/syslog","kubectl get pods"]
ppx = train_char_lm(benign, n=3, alpha=0.5)
print("정상:", ppx("ls -l /tmp"))
print("수상:", ppx("powershell -enc JABFAFo..."))
→ 해석: 퍼플렉서티 ↑ = 훈련 분포에 낯선 옵션/인코딩/LOLBin 패턴.
5. 유사 문서/페이지(5-그램 셰글 + MinHash/LSH)
# pip install datasketch
from datasketch import MinHash, MinHashLSH
def shingles(text, n=5):
return {text[i:i+n] for i in range(max(len(text)-n+1,0))}
docs = ["login page html ...", "login page (modified) ...", "policy report ..."]
signatures=[]
for d in docs:
m = MinHash(num_perm=128)
for s in shingles(d, 5):
m.update(s.encode())
signatures.append(m)
lsh = MinHashLSH(threshold=0.8, num_perm=128)
for i,m in enumerate(signatures):
lsh.insert(f"doc{i}", m)
print(lsh.query(signatures[0])) # doc0와 유사한 문서
→ 용도: 피싱 킷 변종, 웹 변조, 중복 문서 탐지.
6. Elasticsearch/OpenSearch: 오타 허용/부분 일치 검색기
PUT my-index
{
"settings": {
"analysis": {
"tokenizer": {
"my_ngram": { "type": "nGram", "min_gram": 2, "max_gram": 5 }
},
"analyzer": {
"index_ngram": { "type": "custom", "tokenizer": "my_ngram", "filter": ["lowercase"] },
"search_std": { "type": "custom", "tokenizer": "standard", "filter": ["lowercase"] }
}
}
},
"mappings": {
"properties": {
"body": { "type": "text", "analyzer": "index_ngram", "search_analyzer": "search_std" }
}
}
}
- 전략: 색인은 n-그램으로 재현율↑, 검색은 표준 분석기로 정밀도↑.
7. Splunk: 단어 바이그램 카운트
index=mail sourcetype=email
| fields subject
| eval words=split(lower(subject)," ")
| mvexpand words
| streamstats current=f window=1 last(words) as prev
| eval bigram=prev." ".words
| search bigram!=" null"
| stats count by bigram
| sort -count
보안 관점 가이드 & 점검포인트
- 데이터 거버넌스
- PII(이메일·전화 등) 마스킹/가명처리, 보존기간, 접근권한(Role/Mask) 문서화.
- 오탐/과탐 관리
- 모델 점수 + 룰(화이트리스트, 신뢰 TLD, 내부망) 이중 조건, 튜닝 창구(SOC 피드백)를 운영.
- 설명가능성
- 선형계열 모델을 기본 축으로 두고 기여 n-그램 상위 Top-K를 함께 기록/제출 → 감사/포렌식 대응.
- 적대적 회피 대응
- 단어만 쓰지 말고 문자 n-그램도 병행(특수문자/철자 교란 방어).
- 정규화 정책(NFKC/대소문/공백)을 표준화하지만, 로그 원본은 원형 보존.
- 성능/운영
- 드리프트 모니터링(분포 변화, 오탐률), 월간 재학습·사전 업데이트 일정 고정.
- 실시간은 HashingVectorizer + 선형으로 지연/메모리 최소화.
평가 지표(“결과 평가”를 수치화)
- 분류: Precision/Recall/F1(특히 PR-AUC), 비용 민감 임계값 조정.
- 이상탐지: 퍼플렉서티 분포(사분위/변동폭), 임계값 = 평균+Kσ.
- 검색: nDCG@k, Recall@k, 쿼리 오타/부분일치 실험 세트.
- 문체 품질: n-그램 반복률, 희귀도/다양성(Type-Token Ratio, top-k 집중도), 개인 프로파일 근접도.
조직 표준 템플릿(YAML 예시)
usecase: phishing_mail_classification
token_unit:
body: word
url: char
ngram_range:
body: [1, 2]
url: [3, 5]
vectorizer: tfidf
filters:
min_df: 3
max_df: 0.9
model: linear_svm
monitoring:
metrics: [precision, recall, f1, pr_auc]
drift: [feature_distribution, class_balance]
retrain_cycle: monthly
governance:
pii_masking: true
retention_days: 365
explainability:
top_k_ngrams: 15
실전 체크리스트(요약)
- 목표 한 줄 정의(탐지/검색/품질).
- 토큰 단위 선택(문자 vs 단어/형태소, 혼합 권장).
- ngram_range 설정(문자 3–5, 단어 1–2부터).
- 가중치(TF-IDF/LM, 필요 시 스무딩).
- 평가 지표/대시보드(PR-AUC, 퍼플렉서티, nDCG).
- 운영(임계값, 화이트리스트, 월간 재학습, 감사 로그).
- 보안 가드레일(PII, 설명가능성, 적대적 회피 대비).
적용 시나리오 묶음(빠른 스타트)
- A. 보고서 품질 보정: 문체 프로파일 비교로 “AI 티” 지표화 → 편집 가이드 자동 코멘트.
- B. 피싱/스팸: 단어(본문) + 문자(URL) 결합 벡터 → 선형 SVM, 상위 n-그램 근거 출력.
- C. DGA: 문자 n-그램 + 엔트로피 룰 → 점수 기반 티켓화/차단 후보 리스트.
- D. 명령어 이상: 문자 LM 퍼플렉서티 → 상위 1%만 EDR 격리/조사 트리거.
- E. 검색/오타 허용: 색인 n-그램/검색 표준 분석기 → Helpdesk/내부 위키 품질↑.
- F. 유사 문서: MinHash/LSH로 피싱 킷 변종·웹 변조 탐지.
명확한 지시–템플릿–피드백–평가 프레임을 n-그램에 이식하면, 작성 품질 관리부터 보안 탐지/검색까지 하나의 표준 공정으로 운영할 수 있습니다.
728x90
그리드형(광고전용)
댓글