LoginSignup
108
95

More than 5 years have passed since last update.

自然言語のテキストを属性で区分する

Last updated at Posted at 2013-03-18

NSLinguisticTaggerを用いると、自然言語のテキストを品詞(名詞、動詞、代名詞)や「個人名」「地名」といった属性で区分(トークンに分解)することができます。日本語の形態素解析も可能です。

使い方は非常にシンプルで、基本的な手順は

  1. スキームを引数に渡してNSLinguisticTaggerオブジェクトを生成
  2. 処理対象テキストをセット
  3. トークン分解開始

の3ステップです。

objc
// スキーム
NSArray *schemes = @[NSLinguisticTagSchemeLexicalClass];

// NSLinguisticTaggerオブジェクトを生成
NSLinguisticTagger *tagger = [[NSLinguisticTagger alloc] initWithTagSchemes:schemes
                                                                    options:0];

// 処理対象テキスト
NSString *targetText = self.textView.text;
[tagger setString:targetText];

// トークンへの分解開始
[tagger enumerateTagsInRange:NSMakeRange(0, targetText.length)
                      scheme:NSLinguisticTagSchemeLexicalClass
                     options:0
                  usingBlock:
 ^(NSString *tag, NSRange tokenRange, NSRange sentenceRange, BOOL *stop) {

     NSString *subStr = [targetText substringWithRange:tokenRange];
     NSLog(@"%@ : %@", subStr, tag);
 }];
swift
let schemes = [NSLinguisticTagScheme.lexicalClass]
let tagger = NSLinguisticTagger(tagSchemes: schemes, options: 0)

tagger.string = orgStr
let attrStr = NSMutableAttributedString(string: orgStr)

guard let scheme = schemes.first else {fatalError()}
tagger.enumerateTags(in: NSMakeRange(0, orgStr.characters.count), scheme: scheme, options: NSLinguisticTagger.Options(rawValue: 0)) { (tag, tokenRange, sentenceRange, stop) in
    guard let tag = tag else {return}
    attrStr.addAttribute(.foregroundColor as NSAttributedStringKey, value: color(for: tag), range: tokenRange)
}

textView.attributedText = attrStr

スキームとは、トークン分解をどのような属性に基づいて行うかを指定するもので、上記サンプルで使用しているNSLinguisticTagSchemeLexicalClassは品詞(「名詞」「動詞」etc)によってテキストを分解するスキームです。

enumerateTagsInRange:scheme:options:usingBlock:メソッドをコールするとトークン分解が開始され、トークンが見つかるごとに引数 usingBlock に渡されたBloksの処理が実行されます。

品詞で区分する

名詞、動詞といった品詞でテキストを区分するには、スキームとしてNSLinguisticTagSchemeLexicalClassを使用します。

enumerateTagsInRange:scheme:options:usingBlock:メソッドで取得できるタグの種類には、次のようなものがあります。(主なものを抜粋)

  • NSLinguisticTagNoun:名詞
  • NSLinguisticTagVerb:動詞
  • NSLinguisticTagAdjective:形容詞
  • NSLinguisticTagPronoun:代名詞
  • NSLinguisticTagAdverb:副詞
  • NSLinguisticTagConjunction:接続詞
  • NSLinguisticTagPreposition:前置詞
  • NSLinguisticTagParticle:助詞
  • NSLinguisticTagDeterminer:限定詞

たとえば、品詞で区分して色分けする場合、この NSLinguisticTagger で取得できるタグに応じて色を決定するメソッドを実装しておき、

- (UIColor *)colorForAtteributeForLinguisticTag:(NSString *)linguisticTag {

    // 名詞
    if ([linguisticTag isEqualToString:NSLinguisticTagNoun]) {

        return [UIColor redColor];
    }
    // 動詞
    else if ([linguisticTag isEqualToString:NSLinguisticTagVerb]) {

        return [UIColor blueColor];
    }
    // 形容詞
    else if ([linguisticTag isEqualToString:NSLinguisticTagAdjective]) {

        return [UIColor magentaColor];
    }
    // 代名詞
    else if ([linguisticTag isEqualToString:NSLinguisticTagPronoun]) {

        return [UIColor orangeColor];
    }

    return [UIColor whiteColor];
}

次のようにenumerateTagsInRange:scheme:options:usingBlock:メソッドのBlocks内でタグに応じた色分けを実施します。

// スキーム
NSArray *schemes = @[NSLinguisticTagSchemeLexicalClass];

// NSLinguisticTaggerオブジェクトを生成
NSLinguisticTagger *tagger = [[NSLinguisticTagger alloc] initWithTagSchemes:schemes
                                                                    options:0];

// 処理対象テキスト
NSString *targetText = self.textView.text;
[tagger setString:targetText];

// テキストに色をつけるためにNSMutableAttributedStringを生成
NSMutableAttributedString *formatted;
formatted = [[NSMutableAttributedString alloc] initWithString:targetText];

// トークンのタグを取得開始
[tagger enumerateTagsInRange:NSMakeRange(0, targetText.length)
                      scheme:NSLinguisticTagSchemeLexicalClass
                     options:0
                  usingBlock:
 ^(NSString *tag, NSRange tokenRange, NSRange sentenceRange, BOOL *stop) {

     // タグに応じた色分け
     UIColor *color = [self colorForAtteributeForLinguisticTag:tag];
     [formatted addAttribute:NSForegroundColorAttributeName
                       value:color
                       range:tokenRange];
 }];

// 色分けされたテキストを表示
self.textView.attributedText = formatted;

品詞による色分け

地名、個人名、組織名で区分する

スキームとしてNSLinguisticTagSchemeNameTypeを使用します。他は品詞による区分の場合と同じ手順でOKです。

名詞の種別による色分け

スキーム種別

上で使用した NSLinguisticTagSchemeLexicalClass, NSLinguisticTagSchemeNameType 以外に、次のようなスキームが用意されています。

  • NSLinguisticTagSchemeTokenType:「単語」「区切り文字」「ホワイトスペース」「その他」で分解する
  • NSLinguisticTagSchemeLemma:各単語の原形をタグとして取得する
  • NSLinguisticTagSchemeLanguage:言語名("ja", "en",...)をタグとして取得する
  • NSLinguisticTagSchemeScript:書き文字種別("Jpan", "Latn",...)をタグとして取得する
  • NSLinguisticTagSchemeNameTypeOrLexicalClassNSLinguisticTagSchemeLexicalClassまたはNSLinguisticTagSchemeNameTypeにある属性で分解する

言語ごとの対応スキームを確認する

availableTagSchemesForLanguage:メソッドを使用すると、引数に指定した言語で利用できるスキームの配列(NSArray型)を取得することができます。

NSArray *schemes = [NSLinguisticTagger availableTagSchemesForLanguage:@"ja"];

NSLog(@"schemes:%@", schemes);

上記コードの実行結果は、

schemes:(
    TokenType,
    Language,
    Script
)

となりました。(iPhone 6.1 Simulatorで実行)

つまり、"ja"(日本語)で利用できるスキームはNSLinguisticTagSchemeTokenType, NSLinguisticTagSchemeLanguage, NSLinguisticTagSchemeScriptの3種のみであることがわかります。

一方、引数に "en"(英語)を指定しての実行結果は、次のようになりました。

schemes:(
    TokenType,
    Language,
    Script,
    Lemma,
    LexicalClass,
    NameType,
    NameTypeOrLexicalClass
)

英語ではすべてのスキームが利用可能であることがわかります。

日本語の形態素解析を行う

日本語は英語と違い、単語の間がスペースで区切られていません。そこで自然言語処理を行う際のベースとなる処理として、「形態素解析」という、文を形態素(言語で意味を持つ最小単位)に分解する処理が必要となります。

前項でavailableTagSchemesForLanguage:メソッドを用いて調べたとおり、英語と比較すると日本語の対応スキームは少ないですが、NSLinguisticTagSchemeTokenTypeには対応しているので、単語への分解が可能です。すなわち、NSLinguisticTaggerを用いて日本語の形態素解析を行うことができます。

スキームにNSLinguisticTagSchemeTokenTypeを指定し、stringプロパティに日本語の文字列を渡すだけ、つまり英語の場合と実装方法は同じなので、詳細な説明は省略します。

NSStringのカテゴリを利用する

NSLinguisticTagger.h には、NSString のカテゴリも定義されており、NSLinguisticTaggerを使用せず NSStringだけでも同様の処理ができるようになっています。

NSStringに追加されたenumerateLinguisticTagsInRange:scheme:options:orthography:usingBlock:というメソッドを使用します。使い方はNSLinguisticTaggerとほぼ同様です。

NSString *targetText = self.textView.text;

[targetText enumerateLinguisticTagsInRange:NSMakeRange(0, targetText.length)
                              scheme:NSLinguisticTagSchemeLexicalClass
                             options:0
                         orthography:nil
                          usingBlock:
 ^(NSString *tag, NSRange tokenRange, NSRange sentenceRange, BOOL *stop) {

     // トークン取得時の処理
 }];

サンプルコード

Githubにアップしてあります。

LinguisticTaggerSample

参考資料

108
95
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
108
95