iOS MachineLearning 系列(12)—— 自然語言之詞句相似性分析

iOS MachineLearning 系列(12)—— 自然語言之詞句相似性分析

本篇文章將介紹如何使用NaturalLanguage框架來對詞句的相似性進行分析。文本相似性的分析在實際開發中應用很多,比如我們可以通過查找與用戶輸入相似的詞來進行內容推薦。

分析語句的相似性需要進行大量的訓練,NaturalLanguage已經內置了許多語言的訓練模型,使用非常方便。

1 - 文本相似性分析的示例

需要創建NLEmbedding實例來進行詞句的相似性分析。例如:

let embedding = NLEmbedding.wordEmbedding(for: .english)!
let embedding2 = NLEmbedding.sentenceEmbedding(for: .english)!

其中,使用wordEmbedding創建出的實例用來進行單詞分析,sentenceEmbedding創建出的實例用來進行句子分析。其參數設置所分析的語言,需要注意,並非所有語言都支持進行相似性分析。

下面示例代碼演示瞭如何對單詞,句子的相似性進行分析,並能夠自動根據傳入的單詞來進行相近的詞的推薦:

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類來完成:

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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章