在数据分析和机器学习中,处理高基数类别(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)
常见问题和解决方案
- 上下文溢出错误:当类别值列表超出模型的上下文限制时,可以尝试使用向量索引来缩小待处理值的范围。
- 精确匹配困难:通过后处理步骤,将生成的值映射到合法类别值上,可以提高匹配精度。
总结和进一步学习资源
在本文中,我们探讨了几种有效处理高基数类别数据的方法,包括直接匹配、使用向量索引以及生成后修正。每种方法都有其适用场景和限制,选择合适的方法可以有效提高查询分析的准确性和性能。
进一步学习资源:
- LangChain 文档:了解更多关于LangChain库的使用和功能。
- OpenAI API:探索OpenAI 提供的更高级模型及其应用。
参考资料
- OpenAI API 文档:platform.openai.com/docs/
- LangChain 官方文档:www.langchain.com/docs/
如果这篇文章对你有帮助,欢迎点赞并关注我的博客。您的支持是我持续创作的动力!
---END---