しめ鯖日記

swift, iPhoneアプリ開発, ruby on rails等のTipsや入門記事書いてます

【Swift4】形態素解析をやってみる | NSLinguisticTagger

NSLinguisticTaggerというクラスで形態素解析ができるようなので試してみました。

import UIKit

let text = "I have a beautiful pen."
let tagger = NSLinguisticTagger(tagSchemes: NSLinguisticTagger.availableTagSchemes(forLanguage: "en"), options: 0)

tagger.string = text
tagger.enumerateTags(in: NSRange(location: 0, length: text.characters.count), scheme: .tokenType, options: []) { tag, tokenRange, sentenceRange, _ in
    
    let subString = (text as NSString).substring(with: tokenRange)
    print("\(subString) : \(tag?.rawValue ?? "")")
}

文字列を渡した所、下のように分解してくれました。

f:id:llcc:20170921142717p:plain

WhiteSpaceは引数のオプションに.omitWhitespaceを渡すことで除外できます。

let text = "I have a pen."
let tagger = NSLinguisticTagger(tagSchemes: NSLinguisticTagger.availableTagSchemes(forLanguage: "en"), options: 0)

tagger.string = text
tagger.enumerateTags(in: NSRange(location: 0, length: text.characters.count), scheme: .lexicalClass, options: [.omitWhitespace]) { tag, tokenRange, sentenceRange, _ in
    
    let subString = (text as NSString).substring(with: tokenRange)
    print("\(subString) : \(tag?.rawValue ?? "")")
}

f:id:llcc:20170921144430p:plain

日本語の分解も可能です。

let text = "関東機械学習協会員"
let tagger = NSLinguisticTagger(tagSchemes: NSLinguisticTagger.availableTagSchemes(forLanguage: "en"), options: 0)

tagger.string = text
tagger.enumerateTags(in: NSRange(location: 0, length: text.characters.count), scheme: .tokenType, options: []) { tag, tokenRange, sentenceRange, _ in
    
    let subString = (text as NSString).substring(with: tokenRange)
    print("\(subString) : \(tag?.rawValue ?? "")")
}

漢字が並んでいる場合やひらがなが並んでいる場合もうまく取得できました。

f:id:llcc:20170921143620p:plain

f:id:llcc:20170921143634p:plain

enumerateTagsの引数のscemeにlexicalClassを渡すと品詞分解してくれます。

let text = "I have a beautiful pen."
let tagger = NSLinguisticTagger(tagSchemes: NSLinguisticTagger.availableTagSchemes(forLanguage: "en"), options: 0)

tagger.string = text
tagger.enumerateTags(in: NSRange(location: 0, length: text.characters.count), scheme: .lexicalClass, options: []) { tag, tokenRange, sentenceRange, _ in
    
    let subString = (text as NSString).substring(with: tokenRange)
    print("\(subString) : \(tag?.rawValue ?? "")")
}

f:id:llcc:20170921142913p:plain

品詞分解は日本語非対応です。

f:id:llcc:20170921143802p:plain

言語がどのスキーマに対応しているかどうかはavailableTagSchemesを使うと確認できます。

print(NSLinguisticTagger.availableTagSchemes(forLanguage: "en").map { $0.rawValue })
print(NSLinguisticTagger.availableTagSchemes(forLanguage: "ja").map { $0.rawValue })

f:id:llcc:20170921143917p:plain

languageを渡すと言語を判定してくれます。

let text = "I have a beautiful pen."
let tagger = NSLinguisticTagger(tagSchemes: NSLinguisticTagger.availableTagSchemes(forLanguage: "en"), options: 0)

tagger.string = text
tagger.enumerateTags(in: NSRange(location: 0, length: text.characters.count), scheme: .language, options: []) { tag, tokenRange, sentenceRange, _ in
    
    let subString = (text as NSString).substring(with: tokenRange)
    print("\(subString) : \(tag?.rawValue ?? "")")
}

f:id:llcc:20170921143148p:plain

日本語、日本語と英語ミックスでも正しく判定できました。

f:id:llcc:20170921143203p:plain

f:id:llcc:20170921143218p:plain