活动介绍
file-type

深度学习中文本预处理Tokenizer详解与应用

9KB | 更新于2025-11-16 | 84 浏览量 | 0 下载量 举报 收藏
download 立即下载
Tokenizer是深度学习中自然语言处理(NLP)任务中极为关键的预处理工具,其核心功能是将原始文本数据转换为计算机能够理解与处理的数值化序列。在深度神经网络尤其是循环神经网络(RNN)、长短期记忆网络(LSTM)、Transformer架构以及BERT等模型中,输入数据必须以数字形式呈现,因此Tokenizer的作用显得尤为突出。本文围绕“Tokenizer详解[代码]”这一主题,结合描述中的信息,深入剖析Tokenizer的基本原理、实现方法、常用属性及其在英文和中文文本处理中的具体应用,并进一步探讨其在实际项目中的工程意义。 首先,Tokenizer的定义可以概括为:一种将文本字符串分解成基本语义单元(如单词、子词或字符),并将其映射到唯一整数索引的工具。这个过程通常包括三个主要步骤:分词(Tokenization)、构建词汇表(Vocabulary Building)和序列化(Numericalization)。对于英文文本而言,常见的分词方式是基于空格或标点符号进行切分,例如句子 "I love deep learning" 会被分解为 ["I", "love", "deep", "learning"] 四个词元(token)。而中文由于缺乏天然的词边界,需要借助更复杂的分词算法,如jieba分词、THULAC或基于深度学习的分词器来进行有效切分。 在Keras/TensorFlow框架中,`tf.keras.preprocessing.text.Tokenizer` 是一个广泛使用的类,它封装了上述所有功能。该类的主要参数包括 `num_words`(限制词汇表的最大大小,保留频率最高的词汇)、`oov_token`(用于标记未登录词,即词汇表之外的词)、`filters`(指定需要过滤的字符,如标点符号)以及 `lower`(是否将文本转为小写)等。通过调用 `fit_on_texts()` 方法,Tokenizer会遍历训练语料库,统计每个词的出现频率,并建立从词语到整数的映射关系,存储于 `.word_index` 属性中;同时,`.index_word` 则提供反向映射。此外,`.word_counts` 和 `.document_count` 等属性可用于分析语料特征。 完成词汇表构建后,下一步是将文本转换为整数序列。这一步通过 `texts_to_sequences()` 方法实现,它会将每个句子中的词替换为其对应的索引值,输出为列表的列表。例如,若 "I" 映射为1,"love" 为2,则原句将变为 [1, 2, 3, 4]。然而,不同句子长度不一,直接输入神经网络会导致维度不匹配问题。为此,需使用 `pad_sequences()` 函数对序列进行填充或截断,使其统一长度。该函数支持前向填充(pre-padding)和后向填充(post-padding),并可通过 `maxlen` 参数设定最大序列长度,从而确保输入张量具有相同的shape,满足批量训练的需求。 除了基础的词级Tokenizer,现代NLP系统越来越多地采用子词(subword)级别的分词策略,如Byte Pair Encoding(BPE)、WordPiece 和 SentencePiece。这些方法能够在保持词汇量可控的同时,有效处理未登录词问题。例如,BERT模型使用的就是WordPiece Tokenizer,它可以将未知单词拆解为已知的子词组合,如“unhappiness”可能被分为 “un”, “##happy”, “##ness”。这种机制显著提升了模型对罕见词和构词变化的鲁棒性。 在中文处理场景下,Tokenizer的设计更为复杂。由于汉字本身不具备明确的词边界,简单的字符级分割会导致语义信息丢失,而过于依赖外部词典的分词工具又可能存在领域适应性差的问题。因此,当前主流做法是结合字级与词级表示,或直接采用基于字符的Tokenizer配合上下文建模能力强大的神经网络来捕捉语义。此外,像Hugging Face Transformers库提供的 `BertTokenizer` 或 `AutoTokenizer` 支持多语言混合输入,内置了针对中文优化的分词规则,极大简化了开发流程。 值得一提的是,Tokenizer不仅影响模型的输入质量,还直接关系到模型的泛化能力和训练效率。一个设计良好的Tokenizer应具备以下特性:高覆盖率(覆盖绝大多数真实文本中的词汇)、低OOV率(减少未知词出现概率)、合理的稀疏性控制(避免因词汇过大导致计算资源浪费)以及良好的可解释性。在实际应用中,还需注意训练集与测试集之间词汇分布的一致性,必要时应对Tokenizer进行重新训练或微调。 综上所述,Tokenizer作为连接人类语言与机器理解的桥梁,在自然语言处理 pipeline 中扮演着不可替代的角色。无论是传统的机器学习模型还是前沿的预训练语言模型,都离不开高效、精准的文本向量化过程。掌握其工作原理、灵活运用各类分词技术,并结合具体任务需求进行定制化配置,是每一位从事深度学习与NLP研发人员必备的核心技能。通过本文所提及的代码实践与理论解析,读者可系统建立起对Tokenizer的全面认知,为后续构建高质量的语言模型奠定坚实基础。

相关推荐

filetype

请介绍下这段代码的作用“ use_auth_token = kwargs.pop("use_auth_token", None) if use_auth_token is not None: warnings.warn( "The `use_auth_token` argument is deprecated and will be removed in v5 of Transformers. Please use `token` instead.", FutureWarning, ) if kwargs.get("token", None) is not None: raise ValueError( "`token` and `use_auth_token` are both specified. Please set only the argument `token`." ) kwargs["token"] = use_auth_token config = kwargs.pop("config", None) kwargs["_from_auto"] = True use_fast = kwargs.pop("use_fast", True) tokenizer_type = kwargs.pop("tokenizer_type", None) trust_remote_code = kwargs.pop("trust_remote_code", None) gguf_file = kwargs.get("gguf_file", None) # First, let's see whether the tokenizer_type is passed so that we can leverage it if tokenizer_type is not None: tokenizer_class = None tokenizer_class_tuple = TOKENIZER_MAPPING_NAMES.get(tokenizer_type, None) if tokenizer_class_tuple is None: raise ValueError( f"Passed `tokenizer_type` {tokenizer_type} does not exist. `tokenizer_type` should be one of " f"{', '.join(c for c in TOKENIZER_MAPPING_NAMES.keys())}." ) tokenizer_class_name, tokenizer_fast_class_name = tokenizer_class_tuple if use_fast: if tokenizer_fast_class_name is not None: tokenizer_class = tokenizer_class_from_name(tokenizer_fast_class_name) else: logger.warning( "`use_fast` is set to `True` but the tokenizer class does not have a fast version. " " Falling back to the slow version." ) if tokenizer_class is None: tokenizer_class = tokenizer_class_from_name(tokenizer_class_name) if tokenizer_class is None: raise ValueError(f"Tokenizer class {tokenizer_class_name} is not currently imported.") return tokenizer_class.from_pretrained(pretrained_model_name_or_path, *inputs, **kwargs) # Next, let's try to use the tokenizer_config file to get the tokenizer class. tokenizer_config = get_tokenizer_config(pretrained_model_name_or_path, **kwargs) if "_commit_hash" in tokenizer_config: kwargs["_commit_hash"] = tokenizer_config["_commit_hash"] config_tokenizer_class = tokenizer_config.get("tokenizer_class") tokenizer_auto_map = None if "auto_map" in tokenizer_config: if isinstance(tokenizer_config["auto_map"], (tuple, list)): # Legacy format for dynamic tokenizers tokenizer_auto_map = tokenizer_config["auto_map"] else: tokenizer_auto_map = tokenizer_config["auto_map"].get("AutoTokenizer", None) # If that did not work, let's try to use the config. if config_tokenizer_class is None: if not isinstance(config, PretrainedConfig): if gguf_file: gguf_path = cached_file(pretrained_model_name_or_path, gguf_file, **kwargs) config_dict = load_gguf_checkpoint(gguf_path, return_tensors=False)["config"] config = AutoConfig.for_model(**config_dict) else: config = AutoConfig.from_pretrained( pretrained_model_name_or_path, trust_remote_code=trust_remote_code, **kwargs ) config_tokenizer_class = config.tokenizer_class if hasattr(config, "auto_map") and "AutoTokenizer" in config.auto_map: tokenizer_auto_map = config.auto_map["AutoTokenizer"] has_remote_code = tokenizer_auto_map is not None has_local_code = type(config) in TOKENIZER_MAPPING or ( config_tokenizer_class is not None and ( tokenizer_class_from_name(config_tokenizer_class) is not None or tokenizer_class_from_name(config_tokenizer_class + "Fast") is not None ) ) trust_remote_code = resolve_trust_remote_code( trust_remote_code, pretrained_model_name_or_path, has_local_code, has_remote_code ) if has_remote_code and trust_remote_code: if use_fast and tokenizer_auto_map[1] is not None: class_ref = tokenizer_auto_map[1] else: class_ref = tokenizer_auto_map[0] tokenizer_class = get_class_from_dynamic_module(class_ref, pretrained_model_name_or_path, **kwargs) _ = kwargs.pop("code_revision", None) if os.path.isdir(pretrained_model_name_or_path): tokenizer_class.register_for_auto_class() return tokenizer_class.from_pretrained( pretrained_model_name_or_path, *inputs, trust_remote_code=trust_remote_code, **kwargs ) elif config_tokenizer_class is not None: tokenizer_class = None if use_fast and not config_tokenizer_class.endswith("Fast"): tokenizer_class_candidate = f"{config_tokenizer_class}Fast" tokenizer_class = tokenizer_class_from_name(tokenizer_class_candidate) if tokenizer_class is None: tokenizer_class_candidate = config_tokenizer_class tokenizer_class = tokenizer_class_from_name(tokenizer_class_candidate) if tokenizer_class is None: raise ValueError( f"Tokenizer class {tokenizer_class_candidate} does not exist or is not currently imported." ) return tokenizer_class.from_pretrained(pretrained_model_name_or_path, *inputs, **kwargs) # Otherwise we have to be creative. # if model is an encoder decoder, the encoder tokenizer class is used by default if isinstance(config, EncoderDecoderConfig): if type(config.decoder) is not type(config.encoder): # noqa: E721 logger.warning( f"The encoder model config class: {config.encoder.__class__} is different from the decoder model " f"config class: {config.decoder.__class__}. It is not recommended to use the " "`AutoTokenizer.from_pretrained()` method in this case. Please use the encoder and decoder " "specific tokenizer classes." ) config = config.encoder model_type = config_class_to_model_type(type(config).__name__) if model_type is not None: tokenizer_class_py, tokenizer_class_fast = TOKENIZER_MAPPING[type(config)] if tokenizer_class_fast and (use_fast or tokenizer_class_py is None): return tokenizer_class_fast.from_pretrained(pretrained_model_name_or_path, *inputs, **kwargs) else: if tokenizer_class_py is not None: return tokenizer_class_py.from_pretrained(pretrained_model_name_or_path, *inputs, **kwargs) else: raise ValueError( "This tokenizer cannot be instantiated. Please make sure you have `sentencepiece` installed " "in order to use this tokenizer." ) raise ValueError( f"Unrecognized configuration class {config.__class__} to build an AutoTokenizer.\n" f"Model type should be one of {', '.join(c.__name__ for c in TOKENIZER_MAPPING.keys())}." )”

filetype
ee345
  • 粉丝: 23
上传资源 快速赚钱