Text Classification
Transformers
Safetensors
Chinese
spam-detection
advertising-detection
ad-classification
chinese
modernbert
mmbert
multi-task
four-head
Instructions to use x6nux/laya-ad with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- Transformers
How to use x6nux/laya-ad with Transformers:
# Use a pipeline as a high-level helper from transformers import pipeline pipe = pipeline("text-classification", model="x6nux/laya-ad")# pip install -U transformers accelerate # Load model directly from transformers import AutoModel model = AutoModel.from_pretrained("x6nux/laya-ad", device_map="auto") - Notebooks
- Google Colab
- Kaggle
File size: 8,272 Bytes
f8d2531 e2492ec f8d2531 e2492ec f8d2531 e2492ec f8d2531 e2492ec f8d2531 e2492ec f8d2531 e2492ec f8d2531 e2492ec f8d2531 e2492ec f8d2531 e2492ec f8d2531 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 | #!/usr/bin/env python3
"""构建优化训练集:teacher 清洗数据 + 之前 25k 数据合并,广告过采样 + 稀有 kind/severity 补齐。
- teacher 数据优先(同 text),早前数据补充;排除外部测试集文本,避免泄漏
- --gmeow 接入 gmeow 封禁广告语料(ads_final.jsonl,text/label/kind/scope/severity),
--gmeow_val_texts 指定留出 val 文本清单:留出行只进 val(并从 teacher/earlier 中剔除同文本防泄漏)
- normal 的 scope/severity 置 -100(交给二分类 gate),scope/severity 头只学广告
- train 广告过采样到 20%;kind 每类最少 1000;severity 0/1 最少 500/1000
- 重复样本用 marker_augment 生成标记形态变体,降低死记
- 输出 data/optimized_4h/{train,dev,val,holdout827}.jsonl + teacher_holdout/earlier_val
"""
import argparse
import json
import random
from collections import Counter
from pathlib import Path
import numpy as np
from sklearn.model_selection import train_test_split
from marker_augment import augment_markers
KINDS = ["crypto", "gambling", "porn", "porn_bait", "promo", "scam", "spam_flood"]
def load(p):
return [json.loads(l) for l in open(p, encoding="utf-8") if l.strip()]
def key(text: str) -> str:
return "".join(text.split()).lower()
def from_gmeow(r):
sev = r.get("severity")
return {
"text": r["text"],
"label_bin": 0,
"label_kind": KINDS.index(r["kind"]) if r.get("kind") in KINDS else -100,
"label_scope": (0 if r.get("scope") == "account" else 1) if r.get("scope") in ("account", "message") else -100,
"label_sev": int(round(sev)) if isinstance(sev, (int, float)) and 0 <= sev <= 3 else -100,
"source": "gmeow",
}
def from_teacher(r):
is_ad = r.get("label") == "ad"
kind = r.get("ad_kind")
return {
"text": r["text"],
"label_bin": 0 if is_ad else 1,
"label_kind": KINDS.index(kind) if (is_ad and kind in KINDS) else -100,
"label_scope": (0 if r.get("scope") == "account" else 1) if is_ad else -100,
"label_sev": (int(r.get("severity_bucket", -100))) if is_ad else -100,
"source": "teacher",
}
def from_earlier(r):
is_ad = r["label_bin"] == 0
return {
"text": r["text"],
"label_bin": r["label_bin"],
"label_kind": r["label_kind"] if is_ad else -100,
"label_scope": r["label_scope"] if is_ad else -100,
"label_sev": r["label_sev"] if is_ad else -100,
"source": "earlier",
}
def main():
ap = argparse.ArgumentParser()
ap.add_argument("--teacher", default="data/cleaned/archive_latest_full_clean.jsonl")
ap.add_argument("--earlier_train", default="data/processed_4h/train.jsonl")
ap.add_argument("--external_teacher", default="data/processed_teacher/holdout827.jsonl")
ap.add_argument("--external_earlier", default="data/processed_4h/val.jsonl")
ap.add_argument("--out", default="data/optimized_4h")
ap.add_argument("--seed", type=int, default=42)
ap.add_argument("--ad_ratio", type=float, default=0.20)
ap.add_argument("--kind_min", type=int, default=1000)
ap.add_argument("--sev0_min", type=int, default=500)
ap.add_argument("--sev1_min", type=int, default=1000)
ap.add_argument("--gmeow", default=None,
help="gmeow ads_final.jsonl(text/label/kind/scope/severity)")
ap.add_argument("--gmeow_val_texts", default=None,
help="jsonl({text}):gmeow 留出 val 的文本清单")
args = ap.parse_args()
teacher = load(args.teacher)
earlier = load(args.earlier_train)
gmeow_hold, gmeow_in = [], []
if args.gmeow:
hold_keys = set()
if args.gmeow_val_texts:
hold_keys = {key(r["text"]) for r in load(args.gmeow_val_texts)}
gmeow = [from_gmeow(r) for r in load(args.gmeow)
if r.get("label") == "ad" and r.get("kind") in KINDS]
gmeow_hold = [m for m in gmeow if key(m["text"]) in hold_keys]
gmeow_in = [m for m in gmeow if key(m["text"]) not in hold_keys]
print(f"gmeow ads={len(gmeow)} train_pool={len(gmeow_in)} val_hold={len(gmeow_hold)}")
ext_t = [from_earlier(r) if "label_bin" in r else from_teacher(r) for r in load(args.external_teacher)]
ext_e = [from_earlier(r) if "label_bin" in r else from_teacher(r) for r in load(args.external_earlier)]
ext_texts = {r["text"] for r in ext_t + ext_e}
hold_keys = {key(m["text"]) for m in gmeow_hold}
combined = {}
for m in gmeow_in:
if m["text"] not in ext_texts:
combined[m["text"]] = m
for r in earlier:
m = from_earlier(r)
if m["text"] not in ext_texts and key(m["text"]) not in hold_keys:
combined[m["text"]] = m
for r in teacher:
m = from_teacher(r)
if m["text"] not in ext_texts and key(m["text"]) not in hold_keys:
combined[m["text"]] = m
rows = list(combined.values())
print("combined unique", len(rows), "ads", sum(1 for r in rows if r["label_bin"] == 0),
"kind", Counter(r["label_kind"] for r in rows if r["label_kind"] >= 0),
"sev", Counter(r["label_sev"] for r in rows if r["label_sev"] >= 0))
y = np.array([r["label_bin"] for r in rows])
idx = np.arange(len(rows))
tr, rest = train_test_split(idx, test_size=0.10, stratify=y, random_state=args.seed)
dev, rest2 = train_test_split(rest, test_size=0.50, stratify=y[rest], random_state=args.seed)
val, hold = train_test_split(rest2, test_size=0.50, stratify=y[rest2], random_state=args.seed)
splits = {"train": [rows[i] for i in tr], "dev": [rows[i] for i in dev],
"val": [rows[i] for i in val], "holdout827": [rows[i] for i in hold]}
splits["val"] = splits["val"] + gmeow_hold
if gmeow_hold:
print("gmeow val holdout", len(gmeow_hold),
"kind", Counter(KINDS[m["label_kind"]] for m in gmeow_hold if m["label_kind"] >= 0))
train = splits["train"]
rng = random.Random(args.seed)
normals = sum(1 for r in train if r["label_bin"] == 1)
ads = [r for r in train if r["label_bin"] == 0]
target_ads = int(args.ad_ratio / (1 - args.ad_ratio) * normals)
extra = max(0, target_ads - len(ads))
def dup(src, n):
out = []
for i in range(n):
r = dict(rng.choice(src))
r["text"] = augment_markers(r["text"], random.Random(args.seed * 1000 + i), p=0.5)
r["source"] = "oversample"
out.append(r)
return out
train += dup(ads, extra)
for k in range(len(KINDS)):
pool = [r for r in train if r["label_kind"] == k]
if pool and len(pool) < args.kind_min:
train += dup(pool, args.kind_min - len(pool))
for sev, minimum in ((0, args.sev0_min), (1, args.sev1_min)):
pool = [r for r in train if r["label_sev"] == sev]
if pool and len(pool) < minimum:
train += dup(pool, minimum - len(pool))
splits["train"] = train
out = Path(args.out)
out.mkdir(parents=True, exist_ok=True)
for name, data in splits.items():
with open(out / f"{name}.jsonl", "w", encoding="utf-8") as f:
for x in data:
f.write(json.dumps(x, ensure_ascii=False) + "\n")
print(name, len(data), "bin", Counter(x["label_bin"] for x in data),
"kind", Counter(x["label_kind"] for x in data if x["label_kind"] >= 0),
"scope", Counter(x["label_scope"] for x in data if x["label_scope"] >= 0),
"sev", Counter(x["label_sev"] for x in data if x["label_sev"] >= 0))
for name, data in (("teacher_holdout", ext_t), ("earlier_val", ext_e)):
with open(out / f"{name}.jsonl", "w", encoding="utf-8") as f:
for x in data:
f.write(json.dumps(x, ensure_ascii=False) + "\n")
print(name, len(data), "bin", Counter(x["label_bin"] for x in data),
"kind", Counter(x["label_kind"] for x in data if x["label_kind"] >= 0))
print("out", out.resolve())
if __name__ == "__main__":
main()
|