iOS MachineLearning 系列(11)—— 自然语言识别与文本分析

本文涉及的产品
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
NLP 自学习平台,3个模型定制额度 1个月
云解析 DNS,旗舰版 1个月
简介: 在上一篇文章中,我们介绍了使用NaturalLanguage框架来进行自然语言的拆解,可以将一段文本按照单词,句子或段落的模式进行拆解。并且,在进行拆解时,其可以自动的识别所使用的语言。

iOS MachineLearning 系列(11)—— 自然语言识别与单词分析

在上一篇文章中,我们介绍了使用NaturalLanguage框架来进行自然语言的拆解,可以将一段文本按照单词,句子或段落的模式进行拆解。并且,在进行拆解时,其可以自动的识别所使用的语言。

其实,NaturalLanguage框架本身也提供了语言识别的能力,其可以分析一段文本所对应的语言,同样对于包含多种语言的文本,其可以分析出各种语言的占比。语言识别是其他高级自然语言处理任务的基础,本篇文章还将介绍NaturalLanguage关于文本分析的能力,其能够对文本中的人名,地名和组织名进行识别,也可以对词性进行分析,如动词,名词。甚至我们还可以分析文本的积极或消极程度来推测内容的取向,从而帮助开发者开发出更加智能的应用。

1 - 语言识别

NLLanguageRecognizer类用来进行语言识别,其可以对输入的文本所使用的语言进行推断,使用非常简单。

首先初始化一个NLLanguageRecognizer实例,如下:

let recognizer = NLLanguageRecognizer()

可以定义一些示例的字符串来测试识别能力,如:

let string1 = "世界,你好!"
let string2 = "Hello World!"
let string3 = "こんにちは中国"

调用NLLanguageRecognizer实例的processString方法即可对字符串进行解析,这个方法是同步的,解析完成后,通过dominantLanguage属性即可获取到这段文本所使用的最接近的语言,例如上面的示例字符串中,string1和string2是比较单纯的中文和英文,string3是日语,日语中很多字是和中文一样的,因此对其进行识别可能会出现误差,我们也可以使用languageHypotheses方法来获取可能识别出的语言,返回的结果中会对识别出的每种语言的可信度进行标记。上面的字符串识别效果如下:

其中,zh-Hant为汉语,en为英语,ja为日语。

NLLanguageRecognizer类的使用很简单,其中封装属性和方法列举如下:

open class NLLanguageRecognizer : NSObject {
    // 类方法,直接对字符串进行主要语言识别
    open class func dominantLanguage(for string: String) -> NLLanguage?
    // 对一个字符串进行识别任务
    open func processString(_ string: String)
    // 重置状态
    open func reset()
    // 最近一次识别任务的结果
    open var dominantLanguage: NLLanguage? { get }
    // 设置说支持的语言,可以设置只支持某些语言的识别
    open var languageConstraints: [NLLanguage]
    // 获取所有可能的语言,参数可以设置最多返回的结果个数,结果中value约接近1的语言可信度越高
    public func languageHypotheses(withMaximum maxHypotheses: Int) -> [NLLanguage : Double]
}

NLLanguag是描述语言的结构体,支持的语言列举如下:

extension NLLanguage {
    // 不确定的
    public static let undetermined: NLLanguage
    // 阿姆哈拉语
    public static let amharic: NLLanguage
    // 阿拉伯语
    public static let arabic: NLLanguage
    // 亚美尼亚
    public static let armenian: NLLanguage
    // 孟加拉语
    public static let bengali: NLLanguage
    // 保加利亚
    public static let bulgarian: NLLanguage
    // 缅甸语
    public static let burmese: NLLanguage
    // 加泰罗尼亚语
    public static let catalan: NLLanguage
    // 切罗基
    public static let cherokee: NLLanguage
    // 克罗地亚
    public static let croatian: NLLanguage
    // 捷克
    public static let czech: NLLanguage
    // 丹麦语
    public static let danish: NLLanguage
    // 荷兰
    public static let dutch: NLLanguage
    // 英语
    public static let english: NLLanguage
    // 芬兰语
    public static let finnish: NLLanguage
    // 法语
    public static let french: NLLanguage
    // 格鲁吉亚
    public static let georgian: NLLanguage
    // 德语
    public static let german: NLLanguage
    // 希腊语
    public static let greek: NLLanguage
    // 古吉拉特语
    public static let gujarati: NLLanguage
    // 希伯来语
    public static let hebrew: NLLanguage
    // 印地语
    public static let hindi: NLLanguage
    // 匈牙利
    public static let hungarian: NLLanguage
    // 冰岛语
    public static let icelandic: NLLanguage
    // 印度尼西亚语
    public static let indonesian: NLLanguage
    // 意大利语
    public static let italian: NLLanguage
    // 日语
    public static let japanese: NLLanguage
    // 埃纳德语
    public static let kannada: NLLanguage
    // 高棉语
    public static let khmer: NLLanguage
    // 韩国语
    public static let korean: NLLanguage
    // 老挝
    public static let lao: NLLanguage
    // 马来语
    public static let malay: NLLanguage
    // 马拉雅拉姆语
    public static let malayalam: NLLanguage
    // 马拉地语
    public static let marathi: NLLanguage
    // 蒙古语
    public static let mongolian: NLLanguage
    // 挪威语
    public static let norwegian: NLLanguage
    // 奥里亚语
    public static let oriya: NLLanguage
    // 波斯语
    public static let persian: NLLanguage
    // 波兰语
    public static let polish: NLLanguage
    // 葡萄牙语
    public static let portuguese: NLLanguage
    // 旁遮普语
    public static let punjabi: NLLanguage
    // 罗马尼亚语
    public static let romanian: NLLanguage
    // 俄语
    public static let russian: NLLanguage
    // 简体中文
    public static let simplifiedChinese: NLLanguage
    // 锡兰语
    public static let sinhalese: NLLanguage
    // 斯洛伐克语
    public static let slovak: NLLanguage
    // 西班牙语
    public static let spanish: NLLanguage
    // 瑞典语
    public static let swedish: NLLanguage
    // 泰米尔语
    public static let tamil: NLLanguage
    // 泰卢固语
    public static let telugu: NLLanguage
    // 泰语
    public static let thai: NLLanguage
    // 藏语
    public static let tibetan: NLLanguage
    // 繁体中文
    public static let traditionalChinese: NLLanguage
    // 土耳其语
    public static let turkish: NLLanguage
    // 乌克兰语
    public static let ukrainian: NLLanguage
    // 乌尔都语
    public static let urdu: NLLanguage
    // 越南语
    public static let vietnamese: NLLanguage
    // 哈萨克语
    public static let kazakh: NLLanguage
}

2 - 文本分析

文本分析支持对单词进行分析,也支持对句子和段落进行分析。针对不同的需求场景,可以使用不同的方案来分析。在NaturalLanguage框架中,使用NLTagScheme结构体来定义分析方案,支持的方案列举如下:

extension NLTagScheme {
    // 按元素类型进行标记 可以分析出单词,标点符号,空白符
    public static let tokenType: NLTagScheme
    // 比tokenType方案更进一步,还能分析出词性,如动词,名词等
    public static let lexicalClass: NLTagScheme
    // 名称分析方案,如分析出人名,地名,组织名
    public static let nameType: NLTagScheme
    // nameType和lexicalClass的聚合
    public static let nameTypeOrLexicalClass: NLTagScheme
    // 分析词干,如reading分析词干为read
    public static let lemma: NLTagScheme
    // 标记元素的语言
    public static let language: NLTagScheme 
    // 标记元素的ISO规范的脚本
    public static let script: NLTagScheme
    // 分析内容的消极/积极
    public static let sentimentScore: NLTagScheme
}

文本分析的结果会被封装为NLTag结构体,此结构体会包含一个字符串类型的原始值,对于lemma,language,script,sentimentScore分析方案,其结果会直接包装成字符串,其他的分析方案的结果则进行了定义,如下:

extension NLTag {
    // tokenType方案对应的结果
    public static let word: NLTag // 单词
    public static let punctuation: NLTag // 标点
    public static let whitespace: NLTag // 空白符
    public static let other: NLTag // 其他

    // lexicalClass方案对应的结果
    public static let noun: NLTag  // 名词
    public static let verb: NLTag // 动词
    public static let adjective: NLTag // 形容词
    public static let adverb: NLTag  // 副词
    public static let pronoun: NLTag // 代词
    public static let determiner: NLTag // 限定词
    public static let particle: NLTag // 小品词
    public static let preposition: NLTag // 介词
    public static let number: NLTag // 数词
    public static let conjunction: NLTag // 连词
    public static let interjection: NLTag // 感叹词
    public static let classifier: NLTag // 分类词
    public static let idiom: NLTag  // 惯用语
    public static let otherWord: NLTag // 其他单词
    public static let sentenceTerminator: NLTag // 语句终止符
    public static let openQuote: NLTag // 开引号
    public static let closeQuote: NLTag // 闭引号
    public static let openParenthesis: NLTag // 开括号
    public static let closeParenthesis: NLTag // 闭括号
    public static let wordJoiner: NLTag // 连字符
    public static let dash: NLTag // 破折号
    public static let otherPunctuation: NLTag // 其他标点
    public static let paragraphBreak: NLTag // 段落中断
    public static let otherWhitespace: NLTag // 其他空白符
} 

下面,我们来对每种分析方案进行介绍。

tokenType

tokenType方法非常简单,直接对元素类型进行简单分类,效果如下图所示:

lexicalClass

lexicalClass方法相比tokenType更加高级,能够更加细致的单词进行分类,但是需要注意,lexicalClass方案只对英文支持较好。效果如下:

nameType

此方案用来解析文本中的组织名,地名,人名。同样对英文支持较好,如下:

可以看到,其中国家的名字,人名和城市名都正确的解析了出来。

nameTypeOrLexicalClass

此方案无需做过多的解释,只是两种方法的聚合。

lemma

此方案用来分析词干,主要也是针对英文,效果如下:

language与script

这两个方案都是分析元素的语言相关。

sentimentScore

此方案只能用来进行句子和段落的分析,可以推测出文案内容的积极程度,结果越接近1,标明内容的积极性越高,越接近-1表示越消极。例如:

可以看到其对积极和消极的判定还是比较准确,通过测试,目前也只针对英文有效。

最后,我们再来介绍下用来触发文本分析的NLTagger类,在进行分析前,首先需要实例化此类:

let tagger = NLTagger(tagSchemes: [.lexicalClass, .tokenType, .lemma, .nameType, .script, .nameTypeOrLexicalClass, .sentimentScore, .language])

此实例化方法中传入的参数表示要支持的分析方案。使用如下代码来触发分析:

tagger.string = string
tagger.enumerateTags(in: string.startIndex ..< string.endIndex, unit: .paragraph, scheme: .sentimentScore) { tag, range in
    resultLabel.text = (resultLabel.text ?? "").appending("【[\(string[range])]-[\(tag?.rawValue ?? "")]】")
    return true
}

NLTagger类定义如下:

open class NLTagger : NSObject {
    // 初始化方法,设置支持的分析方案
    public init(tagSchemes: [NLTagScheme])
    open var tagSchemes: [NLTagScheme] { get }
    // 要进行分析的字符串
    open var string: String?
    // 获取支持的方案(对不同的拆解方式和语言,所能支持的方案不同)
    open class func availableTagSchemes(for unit: NLTokenUnit, language: NLLanguage) -> [NLTagScheme]
    // 输入文本的主语言
    open var dominantLanguage: NLLanguage? { get }
    // 使用自定义模型来定义方案
    open func setModels(_ models: [NLModel], forTagScheme tagScheme: NLTagScheme)
    open func models(forTagScheme tagScheme: NLTagScheme) -> [NLModel]
    open func setGazetteers(_ gazetteers: [NLGazetteer], for tagScheme: NLTagScheme)
    open func gazetteers(for tagScheme: NLTagScheme) -> [NLGazetteer]
    
    // 如果availableTagSchemes没有支持的方案,可能是有资源为加载到设备,使用此方法尝试请求资源
    open class func requestAssets(for language: NLLanguage, tagScheme: NLTagScheme, completionHandler: @escaping (NLTagger.AssetsResult, Error?) -> Void)
    open class func requestAssets(for language: NLLanguage, tagScheme: NLTagScheme) async throws -> NLTagger.AssetsResult
    
    // 获取元素所在字符串范围
    public func tokenRange(at index: String.Index, unit: NLTokenUnit) -> Range<String.Index>
    public func tokenRange(for range: Range<String.Index>, unit: NLTokenUnit) -> Range<String.Index>
    // 对某个位置的元素进行解析
    public func tag(at index: String.Index, unit: NLTokenUnit, scheme: NLTagScheme) -> (NLTag?, Range<String.Index>)
    // 对某个位置的元素进行解析,返回肯能的结果
    public func tagHypotheses(at index: String.Index, unit: NLTokenUnit, scheme: NLTagScheme, maximumCount: Int) -> ([String : Double], Range<String.Index>)
    // 进行完整解析
    public func enumerateTags(in range: Range<String.Index>, unit: NLTokenUnit, scheme: NLTagScheme, options: NLTagger.Options = [], using block: (NLTag?, Range<String.Index>) -> Bool)
    // 进行范围解析
    public func tags(in range: Range<String.Index>, unit: NLTokenUnit, scheme: NLTagScheme, options: NLTagger.Options = []) -> [(NLTag?, Range<String.Index>)]
    // 手动设置语言
    public func setLanguage(_ language: NLLanguage, range: Range<String.Index>)
    public func setOrthography(_ orthography: NSOrthography, range: Range<String.Index>)
}

其中availableTagSchemes获取到的可用方案不一定准确,有可能是资源未加载,使用requestAssets可以请求资源,如果最终不能支持,可以从其返回的结果判断:

public enum AssetsResult : Int, @unchecked Sendable {
    // 可用
    case available = 0
    // 不可用
    case notAvailable = 1
    // 异常
    case error = 2
}

enumerateTags方法中有一个options参数,此参数可以对分析的过程进行配置,支持的配置项如下:

public struct Options : OptionSet, @unchecked Sendable {
    // 忽略单词类型标记
    public static var omitWords: NLTagger.Options { get }
    // 忽略标点类型标记
    public static var omitPunctuation: NLTagger.Options { get }
    // 忽略空白符标记
    public static var omitWhitespace: NLTagger.Options { get }
    // 忽略其他类型元素标记
    public static var omitOther: NLTagger.Options { get }
    // 拼接多单词的名称
    public static var joinNames: NLTagger.Options { get }
    // 拼接缩进
    public static var joinContractions: NLTagger.Options { get }
}
目录
相关文章
|
6月前
|
机器学习/深度学习 自然语言处理 数据挖掘
探索自然语言处理(NLP)在文本分析中的无限潜能
在信息爆炸的时代,文本数据已经成为人们获取知识和信息的重要来源。自然语言处理(Natural Language Processing,简称NLP)作为一种人工智能技术,正在引领着文本分析的革新。本文将介绍NLP在文本分析中的应用,包括文本情感分析、关键词提取、实体识别等,并探讨其在未来的发展前景。
128 3
|
6月前
|
机器学习/深度学习 人工智能 自然语言处理
自然语言处理(NLP)在文本分析中的应用:从「被动收集」到「主动分析」
过去,文本分析往往是依靠人工阅读、标注和分类。但随着自然语言处理(NLP)技术的发展,文本分析的方式也在发生变化。本文将探讨NLP在文本分析中的应用,介绍NLP技术在不同领域的具体应用案例,并探讨NLP技术未来的发展方向。
105 0
|
1月前
|
自然语言处理 算法 Python
自然语言处理(NLP)在文本分析中的应用:从「被动收集」到「主动分析」
【10月更文挑战第9天】自然语言处理(NLP)在文本分析中的应用:从「被动收集」到「主动分析」
48 4
|
3月前
|
自然语言处理 算法 数据可视化
NLP-基于bertopic工具的新闻文本分析与挖掘
这篇文章介绍了如何使用Bertopic工具进行新闻文本分析与挖掘,包括安装Bertopic库、加载和预处理数据集、建立并训练主题模型、评估模型性能、分类新闻标题、调优聚类结果的详细步骤和方法。
NLP-基于bertopic工具的新闻文本分析与挖掘
|
2月前
|
人工智能 自然语言处理 算法
自然语言处理与文本分析
自然语言处理(Natural Language Processing,NLP)是计算机科学和人工智能领域的一个分支,旨在让计算机理解、生成和处理人类自然语言。文本分析是自然语言处理的一个重要部分,旨在从文本数据中提取有用信息,如关键词、主题、情感等。
32 4
|
3月前
|
自然语言处理 算法 Python
【语言的力量!】NLP揭秘:从零开始,如何将「文字海洋」转化为「智慧宝藏」——探索文本分析的奇妙之旅!
【8月更文挑战第12天】随着互联网的爆炸式增长,每日产生的海量文本信息成为企业和研究者挖掘价值的金矿。本文通过具体代码示例,展示了如何运用Python中的自然语言处理(NLP)工具,完成从文本数据收集到分析的全过程。首先介绍了文本预处理,包括分词、去除停用词和词干提取;接着说明了如何利用TF-IDF等方法提取文本特征;然后演示了情感分析技术,可判定文本情感倾向;最后探讨了主题建模方法,如LDA算法,用于发现文本集中的潜在主题。这些步骤共同构成了一个强大的框架,使我们能够更有效地理解和利用文本数据。
37 1
|
6月前
|
机器学习/深度学习 数据采集 自然语言处理
自然语言处理(NLP)在文本分析中的应用
【5月更文挑战第31天】自然语言处理(NLP)在数字化时代助力文本分析,涉及情感分析、信息提取、文本分类、机器翻译和问答系统等领域。Python示例展示了NLP如何提取文本实体。深度学习技术如RNN、LSTM和GRU推动NLP发展,但语言复杂性、语义理解及数据质量仍是挑战。NLP将在处理海量文本信息和跨语言交流中发挥更大作用,创造新机遇。
120 0
|
6月前
|
机器学习/深度学习 人工智能 自然语言处理
【专栏】自然语言处理NLP在文本分析中的应用、面临的挑战以及未来的发展方向。
【4月更文挑战第27天】本文探讨了NLP在文本分析中的应用,如客户服务、市场分析等领域,同时指出NLP面临的挑战,如语言多样性、歧义消解及大规模数据处理。随着技术发展,NLP将深化跨语言分析和个性化理解,并关注隐私保护。未来,可解释的AI和联邦学习等技术将为NLP带来新机遇,开启更智能的信息处理时代。
502 1
|
6月前
|
机器学习/深度学习 自然语言处理 算法
什么是自然语言处理的文本分析?
【4月更文挑战第8天】
125 9
|
6月前
|
人工智能 自然语言处理 API
自然语言处理:Python中的文本分析与情感分析
【4月更文挑战第12天】本文介绍了Python在自然语言处理(NLP)中的应用,重点关注文本分析和情感分析。Python有两大常用NLP库:NLTK和spaCy,前者提供丰富的处理工具,后者则以高速和精确著称。情感分析方面,推荐TextBlob和VADER,前者简单易用,后者擅长分析社交媒体文本。基本流程包括文本预处理(如去除停用词)、使用库进行分析(如spaCy的词性标注和命名实体识别)和情感分析(如TextBlob的情感评分)。通过学习和实践,可以提升Python NLP技能。
267 2