**高基数类别数据分析:应对查询分析中精确匹配的挑战**

95 阅读4分钟

在数据分析和机器学习中,处理高基数类别(high cardinality categoricals)是一个常见而复杂的问题。特别是在查询分析中,当我们需要对一个类别列进行过滤时,通常必须指定确切的类别值。然而,当类别值数量庞大时,挑战也随之而来。本文将探讨如何在查询分析中有效处理高基数类别值,并提供实用的代码示例和解决方案。

引言

高基数类别通常会在查询分析中带来挑战,特别是当我们希望使用自然语言处理模型(如大型语言模型,LLM)自动生成精确的类别值进行过滤时。如果有效值的数量较少,我们可以通过提示词(prompting)轻松实现。然而,当值的数量非常多时,模型的上下文长度和注意力机制可能变得不够用。本文将介绍几种方法来应对这些挑战。

主要内容

问题概述

当处理高基数的类别数据时,我们可能会面对以下几个问题:

  • 模型上下文限制:大型语言模型对输入的上下文长度有限制,如果类别值过多,可能会导致上下文溢出。
  • 精确匹配:需要模型精确地生成类别值,这在处理大量值时变得困难。
  • 性能与准确度的权衡:需要在模型的性能和生成结果的准确性之间找到平衡。

方法探索

以下是几种处理高基数类别的策略:

1. 添加所有值到提示词中

一种直接的方法是将所有可能的值都添加到提示词(prompt)中。这种方法虽然简单,但当类别值过多时,容易导致上下文溢出。

system = """Generate a relevant search query for a library system.

`author` attribute MUST be one of:

{authors}

Do NOT hallucinate author name!"""
base_prompt = ChatPromptTemplate.from_messages(
    [
        ("system", system),
        ("human", "{question}"),
    ]
)
prompt = base_prompt.partial(authors=", ".join(names))

2. 使用向量索引

另一种方法是使用向量索引来查找最相关的类别值。这可以通过创建一个包含所有类别值的向量数据库来实现,从而仅检索最相关的几个值。

from langchain_chroma import Chroma
from langchain_openai import OpenAIEmbeddings

embeddings = OpenAIEmbeddings(model="text-embedding-3-small")
vectorstore = Chroma.from_texts(names, embeddings, collection_name="author_names")

def select_names(question):
    _docs = vectorstore.similarity_search(question, k=10)
    _names = [d.page_content for d in _docs]
    return ", ".join(_names)

3. 生成后修正

这种方法让模型自由生成类别值,然后使用后处理步骤将生成的值映射到一个合法的类别值上。

from langchain_core.pydantic_v1 import validator

class Search(BaseModel):
    query: str
    author: str

    @validator("author")
    def double(cls, v: str) -> str:
        return vectorstore.similarity_search(v, k=1)[0].page_content

prompt = ChatPromptTemplate.from_messages(
    [
        ("system", system),
        ("human", "{question}"),
    ]
)
corrective_structure_llm = llm.with_structured_output(Search)
corrective_query_analyzer = (
    {"question": RunnablePassthrough()} | prompt | corrective_structure_llm
)

代码示例

以下是一个完整示例,展示如何使用向量索引来处理高基数类别数据:

import os
from faker import Faker
from langchain_openai import ChatOpenAI, OpenAIEmbeddings
from langchain_chroma import Chroma
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.runnables import RunnablePassthrough
from langchain_core.pydantic_v1 import BaseModel, Field, validator

# 使用API代理服务提高访问稳定性
os.environ["OPENAI_API_KEY"] = "your-api-key"

fake = Faker()
names = [fake.name() for _ in range(10000)]

embeddings = OpenAIEmbeddings(model="text-embedding-3-small")
vectorstore = Chroma.from_texts(names, embeddings, collection_name="author_names")

class Search(BaseModel):
    query: str
    author: str

    @validator("author")
    def double(cls, v: str) -> str:
        return vectorstore.similarity_search(v, k=1)[0].page_content

system = """Generate a relevant search query for a library system"""
prompt = ChatPromptTemplate.from_messages(
    [
        ("system", system),
        ("human", "{question}"),
    ]
)
corrective_structure_llm = ChatOpenAI(model="gpt-3.5-turbo-0125", temperature=0).with_structured_output(Search)
corrective_query_analyzer = (
    {"question": RunnablePassthrough()} | prompt | corrective_structure_llm
)

result = corrective_query_analyzer.invoke("what are books about aliens by jes knight")
print(result)

常见问题和解决方案

  • 上下文溢出错误:当类别值列表超出模型的上下文限制时,可以尝试使用向量索引来缩小待处理值的范围。
  • 精确匹配困难:通过后处理步骤,将生成的值映射到合法类别值上,可以提高匹配精度。

总结和进一步学习资源

在本文中,我们探讨了几种有效处理高基数类别数据的方法,包括直接匹配、使用向量索引以及生成后修正。每种方法都有其适用场景和限制,选择合适的方法可以有效提高查询分析的准确性和性能。

进一步学习资源:

  1. LangChain 文档:了解更多关于LangChain库的使用和功能。
  2. OpenAI API:探索OpenAI 提供的更高级模型及其应用。

参考资料

  1. OpenAI API 文档:platform.openai.com/docs/
  2. LangChain 官方文档:www.langchain.com/docs/

如果这篇文章对你有帮助,欢迎点赞并关注我的博客。您的支持是我持续创作的动力!

---END---