第二回 | Google Natural Language API

# 目的
商品レビュー分析のシステム化にあたって、消費者のレビューやレビュー内に登場するエンティティ（キーワード）がポジティブなのかネガティブなのかを分類・数値化することで、定量的な集計・分析が可能になります。レビューの感情分析結果とエンティティの感情分析結果を活用し、消費者が感じる商品の評価やその強みや弱みを明らかにします。

### どういったデータが欲しいか
* レビューのポジティブ/ネガティブ度合い
* エンティティのポジティブ/ネガティブ度合い

### 技術選定の理由
レビューやエンティティの感情分析を行うためには、自然言語処理のモデルを作成する方法がありますが、多様なカテゴリーの商品に対して精度の高い分析を行うためには大量なデータが必要であり、その精度向上には多くの時間も要します。そこで、Googleが提供している「Cloud Natural Language」を使用することで商品レビュー分析の自動化を図りました。また、「Cloud Natural Language」を選定した理由は以下の通りです。

<br>

* **NLP(自然言語処理モデル)の環境構築が容易**
    * 「Cloud Natural Language」はGoogle Cloud上で動作し、API経由で分析したい文章を送信するだけで処理が行われ、結果がJSON形式で返されます。そのため、分析実行者側で分析のための環境構築が不要です。
<br>

* **品質の高い自然言語解析エンジン**
    * Googleが大量のデータを用いてモデルを作成し、エンティティの切り分けや感情分析、係り受け構造の分析など、分析結果の精度が高いと評価されています。
<br>

* **Googleによるアップデート管理**
    * 自然言語解析エンジンの開発やアップデートには多大な開発負荷がかかりますが、Googleが自然言語解析エンジンの開発とアップデートを管理してくれるため、利用者は開発工程を省略して利用できます。


# 環境
### 開発環境
- **OS**: macOS

### 使用したツールのバージョン

- **Python**: 3.10.12
- **google-cloud-language**: 2.11.1

    
# Google Cloudの「Natural Language API」の利用
自然言語処理はGoogle Cloudの「Natural Language API」を利用します。そのため、Google Cloudのプロジェクトを立ち上げ、課金を有効にし、API利用の認証取得と「Natural Language API」の有効化が必要です。
実際の設定方法ですが、公式のHelpを参考にしてください。

> [Google Cloud｜すべてのクイックスタート](https://cloud.google.com/natural-language/docs/quickstarts?hl=ja)  
> [Google Cloud｜クイックスタート: Natural Language API の設定](https://cloud.google.com/natural-language/docs/setup?hl=ja)    

<br>

## サンプルコード
以下のコードを用いることで「レビュー感情分析」と「エンティティ感情分析」を行うことができます。
詳しい説明は[Googleの公式ドキュメント](https://cloud.google.com/python/docs/reference/language/latest/google.cloud.language_v1.types.AnnotateTextRequest)に記載されています。

```python
from google.cloud import language_v1

review = "いちいち外さなくても､買い物出来る点が良かったです。音は室内で聴いてみると､中々良い音質です。"
Type = language_v1.Document.Type.PLAIN_TEXT
Language = "ja"
Encoding_type = language_v1.EncodingType.UTF32
Client = language_v1.LanguageServiceClient()

features = {"extract_document_sentiment": True, "extract_entity_sentiment": True}

document = {"content": review, "type_": Type, "language": Language}
request = language_v1.AnnotateTextRequest(
   document=document, features=features, encoding_type=Encoding_type
)
response = Client.annotate_text(request=request)
```


### **パラメータの説明**
* review
    * 分析対象のテキスト
* Type
    *  ドキュメントの種類
        * PLAIN_TEXT:プレーンテキスト形式
        * HTML:HTML形式
* Language
    *  テキストの言語：日本語
* Encoding_type
    * テキストのエンコーディング形式
* Client
    * Google Cloud Language APIと通信するためのクライアン
* features
    * 分析したい機能を指定するパラメータ
    * 「構文解析」や「文書カテゴライズ」等提供している機能はあります。詳しくは[Google公式ドキュメント](https://cloud.google.com/python/docs/reference/language/latest/google.cloud.language_v1.types.AnnotateTextRequest.Features)を参照してください。

<br>
現在、Google Natural Language APIはlanguage_v1とlanguage_v2の両方が利用可能ですが、この記事ではlanguage_v1を使用しています。その理由は、language_v2にはanalyze_entity_sentimentがなく、エンティティ感情分析が提供されていないからです。

## レビュー/エンティティ感情分析の統合後の返り値

```python
review = "いちいち外さなくても､買い物出来る点が良かったです。音は室内で聴いてみると､中々良い音質です。"
```

上記の文章を分析対象とした際、以下が返り値となります。返り値は少々長いため見たい方は以下の「返り値詳細」を参照してください。



<details><summary>返り値詳細</summary>

```python
sentences {
  text {
    content: "いちいち外さなくても､買い物出来る点が良かったです。"
  }
  sentiment {
    magnitude: 0.9
    score: 0.9
  }
}
sentences {
  text {
    content: "音は室内で聴いてみると､中々良い音質です。"
    begin_offset: 26
  }
  sentiment {
    magnitude: 0.9
    score: 0.9
  }
}
entities {
  name: "買い物"
  type_: EVENT
  salience: 0.324703187
  mentions {
    text {
      content: "買い物"
      begin_offset: 11
    }
    type_: COMMON
    sentiment {
      magnitude: 0.8
      score: 0.8
    }
  }
  sentiment {
    magnitude: 0.8
    score: 0.8
  }
}
entities {
  name: "点"
  type_: OTHER
  salience: 0.261324614
  mentions {
    text {
      content: "点"
      begin_offset: 17
    }
    type_: COMMON
    sentiment {
      magnitude: 0.9
      score: 0.9
    }
  }
  sentiment {
    magnitude: 0.9
    score: 0.9
  }
}
entities {
  name: "音質"
  type_: OTHER
  salience: 0.171048984
  mentions {
    text {
      content: "音質"
      begin_offset: 42
    }
    type_: COMMON
    sentiment {
      magnitude: 0.9
      score: 0.9
    }
  }
  sentiment {
    magnitude: 0.9
    score: 0.9
  }
}
entities {
  name: "音"
  type_: OTHER
  salience: 0.121461615
  mentions {
    text {
      content: "音"
      begin_offset: 26
    }
    type_: COMMON
    sentiment {
      magnitude: 0.1
      score: -0.1
    }
  }
  sentiment {
    magnitude: 0.1
    score: -0.1
  }
}
entities {
  name: "室内"
  type_: LOCATION
  salience: 0.121461615
  mentions {
    text {
      content: "室内"
      begin_offset: 28
    }
    type_: COMMON
    sentiment {
    }
  }
  sentiment {
  }
}
document_sentiment {
  magnitude: 1.9
  score: 0.9
}
language: "ja"
```
</details>

<br>

上記のレスポンスデータを整形すると以下のようになります。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2598043/6b4b22e5-443d-0f9c-93dc-4da3a876ebe1.png" width="100%">


### レビュー感情分析
* **sentiment**
    * レビューの感情表現
        * magnitude(感情表現の強さ)
            * 感情的な表現がどれだけ出現し、強い表現であったかを数値化した値
            * 0から+♾️の間の値。感情表現が強いほど点数が高くなる
        * score(感情表現の方向性)
            * ポジティブな表現であるか、ネガティブな表現であるかを判断できる
            * -1から+1の間の値で表現される。-1に近いほどネガティブであり、+1に近いほどポジティブ。0は中立な表現
               
### エンティティ感情分析
* **salience(重要度)**
    * 対象のエンティティ文章の中心に位置し、重要だと判断されれば点数が高くなる
    * [0-1.0]で表現される。1ほど重要度が高く、0は重要度が低い
      
* **mentions(エンティティの表現)**
    * エンティティの文章中での表現を示す。
    * 現時点では日本語は対応していないため、無視して構いません。
* **begin_offset**
    * entityの開始位置 
* **sentiment**
    * エンティティの感情表現
        * magnitude
            * 感情表現の強さ。感情的な表現がどれだけ出現し、強い表現であったかを数値化した値
            * 0から+♾️の間の値。感情表現が強いほど点数が高くなる
        * score
            * 感情表現の方向性。ポジティブな表現であるか、ネガティブな表現であるかを判断できる
            * -1から+1の間の値で表現される。-1に近いほどネガティブであり、+1に近いほどポジティブ。0は中立な表現
                          
# 苦戦したこと
様々なレビューを試した結果、次のような真逆の結果が得られることがありました。これは化粧品に関するレビューであり、"乾燥しない"ことが好意的に評価される一方で、「乾燥**しにくくなる**」の「**しにくくなる**」という箇所により否定的に評価されたと考えられます。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2598043/9a4fff8e-4274-e716-489c-29976b2d326c.png" width="100%">


### エンティティの補正
弊社で調査した限り、エンティティ感情分析結果がネガティブである一方、レビューの感情分析結果がポジティブの場合、本来のエンティティの意味はポジティブとして使われることが多かったです。したがって、レビューの感情分析結果とエンティティ感情分析結果の組み合わせによる補正が必要だと考えました。弊社で開発したシステムでは、レビューの感情分析結果とエンティティ感情分析結果の正負の組み合わせで補正を行っています。具体的には、レビューの感情分析結果が正でエンティティ感情分析結果が負の場合、エンティティ感情分析結果に-1を乗じることで補正しています。  
<br>
今後はより多くのデータを用いて補正方法を試行錯誤することで精度を向上させていきます。

# まとめ

Cloud Natural Languageを使用することで、レビュー自体の感情分析やレビューに登場するエンティティの感情分析が可能となり、商品などが消費者にとってポジティブな感想を持っているのか、ネガティブな感想を持っているのかを知ることができます。また、APIキーを作成するだけで利用できるため、自然言語処理のモデルを作成する必要もなく、高精度な分析が可能になりました。


# その他記事へのリンク
* [第一回 | 商品レビュー分析のリニューアルに伴う自動化システム構築について](https://qiita.com/venect_qiita/items/afc8e35a579f494d7d60)
* 第二回 | Google Natural Language API
* [第三回 | ChatGPT](https://qiita.com/venect_qiita/items/d53be4b15ad44be8f1db)
* [第四回 | MeCab](https://qiita.com/venect_qiita/items/5123b266478c4796db02)