Ana içeriğe geç

Konudan bağımsız öznitelikler

Şu durumda kullanın: sorguladığınız ve bilinen belgeler farklı konularda olabilir — konuyu sızdırmadan stili yakalayan özniteliklere ihtiyaç duyarsınız. Şu durumda kullanmayın: konu sorunun bir parçasıysa (örneğin, iki belgenin içerik paylaşması gereken bir intihal kontrolü). Bu durumda normal öznitelikleri kullanın. Beklenen sonuç: içerik sözcüğü sinyalinin büyük bölümünü atar; işlev sözcüğü, morfoloji ve noktalama kalıplarını korur.

tamga.forensic altında iki teknik bulunur: Sapkota karakter n-gram kategorilendirmesi ve Stamatatos bozunumu. Her ikisi de herhangi bir aşağı akış doğrulayıcısıyla birleştirilebilir.

Konu geçişleri, klasik stilometrinin gerçek adli veriler üzerindeki en yaygın başarısızlık nedenidir. Bir şüphelinin tehdit mektubu ile kişisel e-postası tipik olarak farklı konulardadır; ancak muhtemelen aynı yazara aittir. Bu durumda filtrelenmemiş karakter n-gram ve sözcük n-gram öznitelikleri konu tespitine dönüşür.

tamga iki tamamlayıcı araç sunar.

Sapkota karakter n-gram kategorileri

Şu durumda kullanın: doğrulama için karakter n-gram öznitelikleri istiyorsunuz ancak konuya duyarlı tam sözcük n-gramlarını çıkarmanız gerekiyor — yalnızca ekler, noktalama komşusu ve boşluk komşusu kategorileri tutulur. Şu durumda kullanmayın: ek filtreleme öznitelik uzayını ~500 boyutun altına düşürecek kadar küçük bir derlem söz konusuysa. Beklenen sonuç: yalnızca seçilen kategorileri içeren seyrek bir sayım matrisi; varsayılan ("prefix","suffix","punct") konular arasında en iyi genelleyen ek odaklı tarifte.

CategorizedCharNgramExtractor, her karakter n-gram oluşumunu (yalnızca dizgiyi değil) kaynak metindeki konumuna göre sınıflandırır. Öznitelik sütunları <ngram>|<category> biçiminde adlandırılır; bu sayede the|whole_word ve the|prefix ayrı kanallar olur — açık ve denetlenebilir.

Yedi kategori:

Kategori Açıklama
prefix sözcük başı + karakter içi (ör., "there" içindeki "the")
suffix karakter içi + sözcük sonu (ör., "running" içindeki "ing")
whole_word tam olarak bir sözcük, her iki uçta sınır
mid_word tek bir sözcüğün tamamen içinde
multi_word iki sözcük arasındaki boşluğu kapsıyor
punct herhangi bir noktalama karakteri içeriyor
space boşluk içeriyor ancak multi_word için yeterli değil

Sapkota et al. (2015), yalnızca ek (prefix + suffix) + punct seçiminin konu geçişli atıflamayı önemli ölçüde iyileştirdiğini göstermiştir — adli dilbilim varsayılanı budur.

from tamga.forensic import CategorizedCharNgramExtractor

extractor = CategorizedCharNgramExtractor(
    n=3,
    categories=("prefix", "suffix", "punct"),  # konudan bağımsız alt küme
    scale="zscore",
    lowercase=True,
)
fm = extractor.fit_transform(corpus)

Stamatatos bozunumu

Şu durumda kullanın: içerik sözcüklerini yer tutucu ile değiştirerek agresif konu kaldırma istiyorsunuz — işlev sözcükleri, morfoloji ve noktalama korunur. Şu durumda kullanmayın: aşağı akışta herhangi bir içerik sözcüğü sinyaline ihtiyaç duyuyorsanız (örn., ayırt edici sözcük dağarcığı üzerinde Zeta). Beklenen sonuç: mevcut herhangi bir çıkarıcıya geçirdiğiniz yeni bir Corpus nesnesi. Modlar: "dv_ma" tüm içerik sözcüklerini maskeler, "dv_sa" POS'a göre seçici biçimde maskeler.

distort_corpus, içeriği maskelerken stili korumak için belgeler üzerinde ön işlem uygular: işlev sözcükleri (function words), noktalama, rakamlar ve boşluk karakterleri aynen bırakılır; içerik sözcüklerinin karakterleri değiştirilir.

İki mod

DV-MA (Bozunum Görünümü — Çoklu Yıldız): her içerik-sözcük karakteri → *. Uzunluk korunur — morfolojik alışkanlıklar (tipik sözcük uzunlukları) görünür kalır.

DV-SA (Bozunum Görünümü — Tek Yıldız): her içerik sözcüğü → tek *. Agresif; yalnızca işlev-sözcük ve noktalama deseni hayatta kalır.

from tamga.forensic import distort_corpus
from tamga import MFWExtractor

distorted = distort_corpus(corpus, mode="dv_ma")

# Aşağı akış çıkarıcıları bozulmuş metni görür — konu sinyali maskelenir.
fm = MFWExtractor(n=200, scale="zscore").fit_transform(distorted)

Kısaltmalar

_TOKEN_RE ve yerleşik işlev-sözcük listesi, yaygın İngilizce kısaltmaları (don't, it's, we'll, they've, …) olduğu gibi korur. o'clock ve kesme işareti içeren diğer içerik sözcükleri, parçalara ayrılmak yerine tek bir bitişik dize olarak maskelenir (ör., *******).

Özel işlev-sözcük listesi

distorted = distort_corpus(
    corpus,
    mode="dv_ma",
    function_words={"the", "a", "of", "to", "and"},   # minimal durdurma listesi
)

Her sözcüğü içerik sözcüğü olarak değerlendirmek için frozenset() geçirin (DV-MA tümüyle * içeren bir metin üretir).

İkisini birleştirme

Sapkota kategorileri + Stamatatos bozunumu temiz biçimde bir araya gelir:

distorted = distort_corpus(corpus, mode="dv_ma")
extractor = CategorizedCharNgramExtractor(
    n=3, categories=("prefix", "suffix", "punct"), lowercase=True
)
fm = extractor.fit_transform(distorted)

Bu, çift konudan bağımsız bir öznitelik kümesi üretir — içerik maskelenmiş metinden çıkarılan ek ve noktalama n-gramları — ve çapraz tür PAN görevlerinde filtrelenmemiş karakter n-gramlarını düzenli olarak geride bırakır.

Referans

CategorizedCharNgramExtractor

Bases: BaseFeatureExtractor

Character n-gram extractor that filters n-gram occurrences by Sapkota category.

Unlike :class:CharNgramExtractor, this classifier counts each OCCURRENCE of an n-gram separately and tags it with the category of its position in the source text. The n-gram string "the" can therefore contribute to multiple category channels.

Feature columns are named "<ngram>|<category>" so the origin of each column is explicit and auditable.

Parameters:

Name Type Description Default
n int

N-gram order (fixed int, no range — ranges are an easy extension but complicate the classification logic enough to be deferred).

3
categories iterable of Category

Which categories to retain. Default: all 7. Set to ("prefix", "suffix") to get the cross-topic-robust affix-only feature set that Sapkota et al. recommend.

None
scale ('none', 'zscore', 'l1', 'l2')

Per-feature scaling applied at transform-time. Same semantics as CharNgramExtractor.

"none"
lowercase bool

Case-fold before extracting n-grams.

False

Examples:

>>> # Cross-topic-robust forensic feature set:
>>> extractor = CategorizedCharNgramExtractor(
...     n=3, categories=("prefix", "suffix", "punct"), scale="zscore", lowercase=True
... )

tamga.forensic.char_ngrams.classify_ngram

classify_ngram(ngram: str, left: str, right: str) -> Category

Classify a single n-gram occurrence.

The n-gram string itself is insufficient — its category depends on the context in which it was extracted. left and right are the characters immediately before and after the n-gram occurrence (or an empty string at document boundaries).

Priority order (following Sapkota et al. 2015 convention):

  1. punct — any punctuation character inside the n-gram wins immediately.
  2. whole_word — both the left and right neighbours are spaces (or empty) AND the n-gram contains no internal whitespace.
  3. multi_word — contains internal whitespace.
  4. prefix — left neighbour is space/empty and the last char is a word-internal letter.
  5. suffix — right neighbour is space/empty and the first char is word-internal.
  6. space — contains whitespace but not enough of a word-boundary match for the above categories (rare; gaps at the start or end).
  7. mid_word — otherwise.

tamga.forensic.distortion.distort_corpus

distort_corpus(corpus: Corpus, *, mode: DistortionMode = 'dv_ma', function_words: frozenset[str] | set[str] | list[str] | None = None, language: str | None = None) -> Corpus

Produce a new Corpus with each document's text distorted.

Document ids and metadata are preserved unchanged; metadata["distortion_mode"] is set on each new Document to record how it was produced.

Parameters:

Name Type Description Default
corpus Corpus
required
mode ('dv_ma', 'dv_sa')
"dv_ma"
function_words iterable of str

Words to preserve verbatim. If None, the bundled list for language (or corpus.language when language is not given) is used.

None
language str

Language code overriding corpus.language for function-word selection.

None

tamga.forensic.distortion.distort_text

distort_text(text: str, *, mode: DistortionMode = 'dv_ma', function_words: frozenset[str] | set[str] | list[str] | None = None, language: str = 'en') -> str

Apply Stamatatos distortion to a single string.

Parameters:

Name Type Description Default
text str

Input text.

required
mode ('dv_ma', 'dv_sa')

Distortion variant. dv_ma preserves word length; dv_sa collapses each content word to one *.

"dv_ma"
function_words iterable of str

Words to preserve verbatim. If None, the bundled list for language is used.

None
language str

Language code ("en", "tr", "de", "es", "fr") selecting the bundled function-word list when function_words is None. Ignored otherwise.

'en'

Returns:

Type Description
str

The distorted text — identical length to the input for DV-MA, shorter for DV-SA. All non-word characters (spaces, punctuation, digits) are preserved.