训练 Prize(第2部分):以 0.08 美元 创建 5,500 行数据集
Source: Dev.to
引言:一个“周末项目”的节奏
欢迎阅读我构建 Prize——我的文本分类神经网络的第二篇日志。先说清楚,Prize 官方上是一个周末项目。和你们一样,我有全职工作和其他责任,所以只能在周六、周日戴上“机器学习工程师”的帽子。进度会持续,但会按自己的节奏前进。
在上一篇文章中我定义了网络结构。今天我来讲讲我如何解决任何 AI 项目中最大的问题:获取数据。
第一步:手动清洗
我的第一批数据来源是一个药店连锁的 6 000 条商品库存。听起来很棒,直到你打开文件。
神经网络会学习你教给它的东西。如果我教它把“可口可乐”当作药品,网络就会出错。我发现我的库存被污染了,里面混杂了很多与健康无关的商品。于是我只能动手做脏活。整个周末,我分几次手动筛选列表,删除了数百行包含软饮、巧克力、清洁剂、扫帚和蚂蚁药的记录。
最终得到的干净文件是:inventarioSoloMedicinas.txt。这工作枯燥却至关重要。没有这一步的清洗,Prize 将毫无机会。
第二步:合成数据工厂(投入 $0.08)
真正的挑战来了。药店那边有几千条商品,而“牙科实验室”只有大约 50 条示例,极度不平衡。我需要把这 50 条扩展到 5 500 条,以匹配药店的规模。解决方案?用 AI 训练 AI。
借助 Google Gemini,我写了一个 Python 脚本,调用 OpenRouter 的 API(使用 Llama 3 模型)。思路很简单:
- 取 5 条真实的牙科服务示例。
- 让 AI 生成 20 条用户可能的搜索表达(包括行话、打字错误、不同语气)。
- 重复上述过程,直至达到目标数量。
生成脚本
import requests
import json
import random
import time
import os
# --- CONFIGURACIÓN ---
API_KEY = "XXXXXXXXXX"
OUTPUT_FILE = "dataset_laboratorio_sintetico.txt"
TARGET_COUNT = 5500
BATCH_SIZE = 20 # Cuántas frases pedimos por llamada
MODEL_ID = "meta-llama/llama-3.1-70b-instruct"
semillas_laboratorio = [
"protesis total superior acrilico",
"reparacion de puente fijo",
"ferula de descarga rigida",
"corona de zirconio sobre implante",
# ... Aquí va el resto de los 50 items ...
]
def generate_variations(seeds):
seeds_text = "\n".join([f"- {s}" for s in seeds])
prompt = f"""
Actúa como un generador de datos para entrenar una IA.
Tu tarea es generar {BATCH_SIZE} frases de búsqueda DISTINTAS basadas en los servicios de un laboratorio dental.
Aquí tienes algunos ejemplos reales (semillas):
{seeds_text}
INSTRUCCIONES:
1. Genera {BATCH_SIZE} variaciones nuevas. NO copies las semillas exactamente.
2. Contexto: Usuarios en Venezuela/Latinoamérica buscando estos servicios.
3. Variedad:
- Usa sinónimos (ej: "plancha" en vez de "prótesis", "férula" en vez de "placa").
- Mezcla tonos: Formal ("necesito una cotización..."), Informal ("cuanto cuesta la plancha..."), Directo ("precio corona").
- Incluye ocasionalmente errores leves de ortografía o falta de tildes (como escribe la gente en WhatsApp).
4. FORMATO DE SALIDA: Únicamente una lista JSON pura de strings. Sin texto extra antes ni después.
Ejemplo: ["frase 1", "frase 2", "frase 3"]
"""
headers = {
"Authorization": f"Bearer {API_KEY}",
"Content-Type": "application/json"
}
data = {
"model": MODEL_ID,
"messages": [
{"role": "system", "content": "Eres un asistente útil que responde SOLO en formato JSON válido."},
{"role": "user", "content": prompt}
],
"temperature": 0.8
}
try:
response = requests.post(
"https://openrouter.ai/api/v1/chat/completions",
headers=headers,
json=data
)
response.raise_for_status()
result = response.json()
content = result['choices'][0]['message']['content']
return json.loads(content)
except Exception as e:
print(f"Error en la llamada a la API: {e}")
return []
def main():
print("--- Iniciando Generación para Proyecto Prize ---")
print(f"Meta: {TARGET_COUNT} frases.")
current_count = 0
if os.path.exists(OUTPUT_FILE):
with open(OUTPUT_FILE, 'r', encoding='utf-8') as f:
current_count = len(f.readlines())
print(f"Progreso actual: {current_count} frases encontradas en {OUTPUT_FILE}")
while current_count < TARGET_COUNT:
mis_semillas = random.sample(semillas_laboratorio, k=min(5, len(semillas_laboratorio)))
print(f"Generando lote... (Total actual: {current_count})")
nuevas_frases = generate_variations(mis_semillas)
if not nuevas_frases:
print("Fallo en este lote, reintentando en 5 segundos...")
time.sleep(5)
continue
with open(OUTPUT_FILE, 'a', encoding='utf-8') as f:
for frase in nuevas_frases:
f.write(frase + "\n")
current_count += len(nuevas_frases)
time.sleep(1)
print("\n¡ÉXITO! Generación completada.")
print(f"Archivo guardado en: {OUTPUT_FILE}")
if __name__ == "__main__":
main()
结果:硬数据
- 运行时间: 2 小时。
- 生成量: 5 500 条独特且多样的文本行。
- API 总费用: $0.08 USD。
是的,花不到 10 美分,我就生成了一个稳健且平衡的数据集,手工完成需要几周时间。任务完成。合成数据集已经准备好。
结论
现在我的硬盘上有两个价值连城的文件:
- inventarioSoloMedicinas.txt – 真实、干净的数据。
- dataset_laboratorio_sintetico.txt – 生成的、多样化的数据。
天平已经平衡:约 11 000 条高质量示例,随时可以进行后续处理。下个周末,我将进行数学魔法:再次调用 OpenRouter API 将所有文本转化为向量(embeddings),再把行向量转为列向量(network2.py 脚本所需的格式),最后启动 Prize 进行首次训练。
下个星期六见!