iOS MachineLearning 系列(12)—— 自然语言之词句相似性分析 本篇文章将介绍如何使用NaturalLanguage框架来对词句的相似性进行分析。文本相似性的分析在实际开发中应用很多,比如我们可以通过查找与用户输入相似的词来进行内容推荐。
分析语句的相似性需要进行大量的训练,NaturalLanguage已经内置了许多语言的训练模型,使用非常方便。
1 - 文本相似性分析的示例 需要创建NLEmbedding实例来进行词句的相似性分析。例如:
1 2 let embedding = NLEmbedding .wordEmbedding(for : .english)!let embedding2 = NLEmbedding .sentenceEmbedding(for : .english)!
其中,使用wordEmbedding创建出的实例用来进行单词分析,sentenceEmbedding创建出的实例用来进行句子分析。其参数设置所分析的语言,需要注意,并非所有语言都支持进行相似性分析。
下面示例代码演示了如何对单词,句子的相似性进行分析,并能够自动根据传入的单词来进行相近的词的推荐:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 let label = UILabel (frame: CGRect (x: 0 , y: 100 , width: view.frame.width, height: 500 ))label.numberOfLines = 0 label.text = "" view.addSubview(label) let word = "dog" let word2 = "cat" let word3 = "teacher" let distance = embedding.distance (between: word, and: word2)let distance2 = embedding.distance (between: word, and: word3)label.text = label.text!.appending("单词1:\(word)\n单词2:\(word2)\n单词3:\(word3)" ) label.text = label.text!.appending("\n\n单词1与单词2间的距离:\(distance)\n单词1与单词3间的距离:\(distance2)" ) embedding.enumerateNeighbors(for : word3, maximumCount: 5 , using: { item, distance in label.text = label.text!.appending("\n与单词3相近的词:\(item) - \(distance)" ) return true }) let sen = "Hello, Xiao." let sen2 = "Hi, Xiao." let sen3 = "My name is Xiao." let distance3 = embedding2.distance (between: sen, and: sen2)let distance4 = embedding2.distance (between: sen, and: sen3)label.text = label.text!.appending("\n\n\n句子1:\(sen)\n句子2:\(sen2)\n句子3:\(sen3)" ) label.text = label.text!.appending("\n\n句子1与句子2间的距离:\(distance3)\n句子1与句子3间的距离:\(distance4)" )
计算出的矢量距离越大,标明词句间的差异越大,即相似性越差。效果如下图所示:
通常矢量距离小于1的词句相似性较高。取值范围为0-2之间。
2 - 关于NLEmbedding类 要进行词句的相似性分析,需要NLEmbedding类来完成:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 open class NLEmbedding : NSObject { open class func wordEmbedding (for language : NLLanguage ) -> NLEmbedding ? open class func wordEmbedding (for language : NLLanguage , revision : Int ) -> NLEmbedding ? // 创建分析句子的实例 open class func sentenceEmbedding (for language : NLLanguage ) -> NLEmbedding ? open class func sentenceEmbedding (for language : NLLanguage , revision : Int ) -> NLEmbedding ? // 判断词汇表是否包含参数字符串 open func contains (_ string : String ) -> Bool // 向量空间维数 open var dimension : Int { get } open var vocabularySize: Int { get } open var language: NLLanguage ? { get } open var revision: Int { get } open class func supportedRevisions (for language : NLLanguage ) -> IndexSet open class func supportedSentenceEmbeddingRevisions (for language : NLLanguage ) -> IndexSet // 当前默认的算法版本 open class func currentRevision (for language : NLLanguage ) -> Int open class func currentSentenceEmbeddingRevision (for language : NLLanguage ) -> Int // 计算两个字符串之间的向量距离 public func distance (between firstString : String , and secondString : String , distanceType : NLDistanceType = .cosine ) -> NLDistance // 计算参数字符串的空间向量数据 public func vector (for string : String ) -> [Double ]? // 获取相似的词句,maxCount 控制最大返回个数 public func enumerateNeighbors (for string : String , maximumCount maxCount : Int , distanceType : NLDistanceType = .cosine , using block : (String , NLDistance ) -> Bool ) public func neighbors (for string : String , maximumCount maxCount : Int , distanceType : NLDistanceType = .cosine ) -> [(String , NLDistance )] // 通过空间向量数据来获取相似的词句 public func enumerateNeighbors (for vector : [Double ], maximumCount maxCount : Int , distanceType : NLDistanceType = .cosine , using block : (String , NLDistance ) -> Bool ) public func neighbors (for vector : [Double ], maximumCount maxCount : Int , distanceType : NLDistanceType = .cosine ) -> [(String , NLDistance )] }
其中NLDistance是Double类型的一个别名。直接使用这些API实际上并不能很好的支持中文,NaturalLanguage也支持我们使用自定义的模型,关于模型的使用和训练,我们后面文章会再介绍。
完整的示例代码可以在如下地址找到:
https://github.com/ZYHshao/MachineLearnDemo