SPSS Modelerでテキストマイニングをやってみる その4 活用編

# 感情分析、形態素解析データを使って分析してみる

こんにちは。前々回、前回の２回でModelerにおける日本語のテキストマイニングについて説明しました。

https://qiita.com/harrowharrow16/items/a3ac51a91080c21da87d

https://qiita.com/harrowharrow16/items/ff2bc3bb7574f2811680


今回はその結果を使って、簡単なデータ加工や分析をしてみようと思います。但し、サンプルデータなので、結果は期待せずに活用方法に着目してください。m(_ _)m

**※. 2025/03/13 GitHubに本記事で使用したデータとストリームをアップロードしました。**

https://github.com/harrow16/Qiita/tree/main/TextMining_Part4_1008



## 分析内容
1. ワードクラウド
2. アソシエーション分析
3. コレスポンデンス分析

上記の3つをやってみようと思います。

### 1. 準備
扱うデータは前回までに作成した分析結果のデータを活用します。サンプル数を50件に絞り込んだ状態で説明していましたが、ここでは、感情分析500件、形態素解析500件とした結果データを使います。単純にサンプリングノードの件数を500件にして、タブ区切りのデータでエクスポートしました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3839172/c45fc34d-46f5-a983-6485-9b15f147562f.png)

それぞれのデータを新しいストリームで読み込み、IDで結合します。
Sentenceフィールドはフィルタータブで除外しておきましょう。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3839172/f8215a7b-f52d-ac8f-98f6-4a38aa66a1d2.png)

ここまでが、基本的な準備となります。


### 1. ワードクラウド

#### ①. 条件抽出
ワードクラウドは、v18.2から実装されたModelerの標準機能「データ表示」で簡単に行えます。
単語数が多いので品詞を"名詞-一般"に絞りこんで実施してみます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3839172/d67538b6-185b-b80a-f228-307a3b021a5f.png)


#### ②. データ表示機能の呼び出し
条件抽出ノードの上で右クリックして、メニューから「データ表示」を選択します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3839172/85099373-7ea5-e179-c36f-d53612b52c17.png)


#### ③. ワードクラウドの設定
データ表示機能画面が開いたら、「視覚化する列」に"原形"を選択して、画面上部にある「ワードクラウド」をクリックします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3839172/72429900-a6a1-9eb9-dc6b-4606c5896ef4.png)


#### ③. ワードクラウドの確認

はい、一瞬でワードクラウドが表示されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3839172/586fcd5d-d149-d735-3d53-892306e1649c.png)

さらに、条件抽出ノードを使って、label（感情）を"POSITIVE"に絞ると下記のようなワードクラウドになります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3839172/9253aeff-e404-d7bd-6d0b-3a6431a1f5ac.png)


"NEGATIVE"の場合等、いろいろな切り口で条件を絞って内容を比較することも簡単です。
レビューの内容などでも活用できると思います。


### 2. アソシエーション分析
　共起ネットワークをイメージして関連の強い単語の組み合わせをアソシエーションモデルで発見してみます。

以下が、ストリーム全体です。レコード結合部分までは準備部分と一緒です。

 ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3839172/a4d56585-a9a6-1f5e-3a65-14be1de84a2e.png)


#### ①. 品詞、感情選択
まずは、単語数が多いので品詞を"名詞"、"動詞"、"形容詞"の3つに絞ります。

条件抽出ノードの条件文では、"startstring"関数を使っていて、品詞フィールドの値の先頭２文字が"動詞"、"名詞"、"形容"であったらという意味になります。あと、"名詞-サ変接続"を除外しています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3839172/6f195e2e-de73-5596-34be-76c89612a6d8.png)

つづいて、感情は"POSITIVE"のみにします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3839172/697c4510-cb09-816d-1cf5-f67853113a81.png)


#### ②. フラグノード設定

フラグ設定ノードでフィールド値を利用するために、データ型ノードで"値を読み込み"を行います。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3839172/c1501e78-2362-1857-9345-45c42eaacf87.png)

フラグ設定ノードでは、"原形"フィールドの値をフラグ型フィールドに展開します。
利用環境なセット値では、数値のみの要素は除外しました。

フラグは、真：1、偽：0とし、IDで集計しました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3839172/cffdc473-4274-a0fb-f204-f76e72de929a.png)

プレビューで確認した結果は、下記画面の通り、ID別に各要素のフラグ型のフィールドができています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3839172/3468812e-40d5-87fd-4194-3e69002dd955.png)



#### ③. アソシエーションモデル作成
　では、アソシエーションモデルを作っていきます。
 データ型ノードで、ID以外の全フラグ型フィールドの「ロール」を"両方"に設定します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3839172/3a252c5e-c7b2-7dbb-6a1e-228db3978f65.png)

　アソシエーションモデルは、「Apriori」を使います。設定は、「最低サポート（%）」を"2"%、「最小ルール確信度」は"50"%として、実行します。
※. 閾値は状況によって変えてください。今回は上記設定くらいまで下げないと、ルールが発見できませんでした。
 

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3839172/fa8afaa5-acf5-e938-48da-b5431691f1dd.png)

　作成されたモデルナゲットを確認しましょう。"POSITIVE"な内容では、"映画"と"人"や、"オヤスミナサイ"と”する"などの関係が確認できます。（日々の何気ないつぶやきみたいなデータなので、こんな感じでしょうね。）
 誰かと映画を見たりして、楽しんでいるみたいですね。

 
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3839172/981e5eb6-4385-2baf-48d6-33d67d0b5211.png)

商品レビューなどでも、関連の強いワードを探して分析に役立ててください。


#### ④. 補足

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3839172/eec2b5a0-23ca-3a40-6ed6-3342ca6feb3c.png)

 WEBグラフノードで描画も可能ですが、対象となるフィールド数も多いため、今回は、WEBグラフノードは使用しておりません。（パフォーマンスに難があります。）
 

### 3. コレスポンデンス分析
　最後にコレスポンデンス分析をしてみましょう。GUIでやる場合はModelerとSPSS Statisticsと連携させることで実現可能ですが、今回のデータの場合ちょっと加工が大変になります。 
 ※. SPSS Statisticsでコレスポンデンス分析するためには、カテゴリデータを数値データに置き換え、ラベルにも値を設定する必要があります。1(男性),2(女性),3(不明)のように。
 以下のような形でデータを加工してから、Statisticsノードにデータを渡すのですが、ちょっと大変です。
 ⇒の右側で日本語になっているのは、ラベル値を設定しているからです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3839172/0ba72026-d6fa-49dd-6914-b456699aef4b.png)


  今回も拡張ノードを使います。シンタックスはRを使ってやってみます。ここまでPythonで書いてきたのになんで、と思われますが、Rの方がシンプルなんですよね。

そのため以下のようなクロス集計のような形にデータを加工してからコレスポンデンス分析をしようと思います。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3839172/b067b4ea-5e45-167a-8dcf-a53c17f3cb01.png)


以下が、ストリームの全体です。ちょっとノード数が多くみえますが簡単に実装できます。


 ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3839172/dff1ef0d-55d5-0862-4432-57b3196d4caa.png)

 10/17 追記

RではなくてPythonを使いたいユーザーさん向けの記事も書きました。
※.拡張ノードの部分のみです。データ加工までは一緒です。
 
 https://qiita.com/harrowharrow16/items/56770bf38f5e20a799dd


#### ①. 準備
 拡張ノードでRを使うためには、Modelerがサポートするバージョンの「R」と「Essential for R」というRと連携させるアプリケーションの導入が必要になります。
 Modelerがv18.5のため、以下の構成で実施しています。

 ※.当初、Rのバージョンを4.2.3としておりましたが、Rのサポート対象が変更になったため、
 v4.4.1で動作確認し、変更しました。


|項目    |バージョン                |
|----------|--------------------------|
|R  |4.4.1(windows版)        |
|Esseintial for R |18.5|

RのWindows版は以下のURLからR-4.4.1-win.exeをダウンロードしてインストールしてください。

 https://cran.r-project.org/bin/windows/base/old/4.4.1/

Essential for Rは以下のURLを参考にIBM Passport AdvantageのサイトからModelerのバージョンにあったものをダウンロードしてください。

https://www.ibm.com/docs/ja/spss-modeler/18.5.0?topic=instructions-download-install-spss-modeler-essentials-r

インストールはGUIで簡単に行えます。

以下の記事は、v18.2の時のものですが、基本はバージョンが異なるだけで手順は一緒のため、参考にして準備をお願いします。

https://qiita.com/spssfun2017/items/0bb68e0b577e02bb8c6a

#### ②. 要素の絞り込み
　まずは、コレスポンデンス分析で使用する単語（要素）を絞り込みます。ここでは、品詞を"名詞-一般"に絞り込み、そのあと頻出要素TOP25のみにしています。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3839172/f3ba25ae-a287-fc1d-c889-7f0cc159b688.png)

##### a. 品詞の絞り込み
　品詞をワードクラウドを作成した場合と同様に"名詞-一般"に絞ります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3839172/686a442d-0d8f-6892-e40a-c32ddd6b79cb.png)

##### b. 単語の出現数をカウント
　原形のフィールド値別にレコード数を算出します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3839172/c1157d2d-ecfc-6609-1a2d-5edd7607619e.png)


##### c. ソートして、サンプリング
　多い順にソートしてから、25個のみを抽出

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3839172/82f0ee3c-9fe2-b112-9c10-4073c3058db5.png)


##### d. 元データと内部結合してTOP25が含まれるレコードを抽出
　TOP25の"原形"フィールド値を元データと内部結合することで、TOP25の原形フィールド値を含むレコードのみに絞ることができます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3839172/4165e5f8-d848-2346-eff2-98366fefd603.png)


　ここまでのデータ加工の結果はこんな感じです。

 ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3839172/8e265240-b481-2ec1-5932-772141aad71b.png)




#### ③. コレスポンデンス分析用にデータを整形
　仕上げに再構成ノードで原形フィールドの値をフィールドに展開して感情（label）毎に集計します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3839172/d42795f1-305c-a1df-d87a-95e4a586d179.png)


##### a. データ型で値の読み込み
　再構成ノードで"原形"フィールドの値を読み込むために、データ型ノードで「値の読み込み」を実施します。

 ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3839172/58814e3a-d072-bca1-f92b-143d90c7068d.png)

##### b. 原形フィールド値をフィールド展開して横持ちに

　再構成ノードで原形の値を使って新規フィールドを作成します。
 フィールドには、数値フラグをセットしておき、後で集計できるようにしておきます。
 
 ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3839172/b4c65318-aa55-842e-2c08-aabaf6f95387.png)


 フィールド展開して横持ちにすると以下のようになります。

 ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3839172/ac68d661-5bef-1fdd-911f-82305af026bc.png)

##### c. 感情別の合計を計算して準備完了

　感情別にフラグ値の合計を算出します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3839172/2af4d5e9-cf4a-1135-08e8-1790e91e4601.png)

　すると、クロス集計のような形にデータを加工できたことが確認できます。
 ここまでくれば、あとはコレスポンデンス分析をするだけです。

 ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3839172/3ccec7d7-e3e1-bbcc-3726-870b98051019.png)


#### ④. コレスポンデンスの実施
　拡張の出力ノードでコレスポンデンス分析を実施します。使うシンタックスはRです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3839172/0b05aa34-50d0-d2ea-84b5-8c08bec3ce11.png)

 10/17 追記

RではなくてPythonを使いたいユーザーさん向けの記事も書きました。
 
 https://qiita.com/harrowharrow16/items/56770bf38f5e20a799dd


##### a. 拡張の出力ノード設定
　拡張の出力ノードで、シンタックスの種類に"R"を選択します。
 そして、Rシンタックスをテキストボックスに記述します。

 
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3839172/3b2b6b91-8b60-a9b3-c5b4-fef496313690.png)

##### b.　コレスポンデンス分析シンタックス
　Rのシンタックスの全体を以下に示します。

```R:シンタックス全体
#MASSを利用
library(MASS)

#Modelerからデータを入力
mdDf <- modelerData

#感情列(label)をラベルに設定
rownames(mdDf) <- mdDf$"label"

#感情列(label)を削除
mdDf <- mdDf[, -1]     

#コレスポンデンス分析実施 2次元
corresp_result<-corresp(mdDf,nf=2)

# プロットエリアのサイズを指定して描画
par(mai = c(0, 0, 0, 0))  # 余白を設定 (下, 左, 上, 右) の順でインチ単位
#par(pin = c(10, 8))  # プロットエリアのサイズ (横 10 インチ、縦 8 インチ)

# 結果の表示
print(corresp_result)

# 図のプロット
plot(corresp_result, main = "Correspondence Analysis using MASS")
```

###### b-1.　ライブラリ読み込み
詳細をみていきましょう。
まずは、MASSライブラリを読み込みます。
導入していない方は、事前にRの環境に導入しておいてください。

```R:ライブラリ読み込み
#MASSを利用
library(MASS)
```

###### b-2.　データ読み込み
Modelerからのデータはデータフレームで読み込みます。
modelerDataと書けばModelerから読み込みができます。

```R:データ読み込み
#Modelerからデータを入力
mdDf <- modelerData
```

###### b-3.　行ラベルの設定
今回は、感情（label)フィールドの値を行に設定します。

```R:行データの設定
#感情列(label)をラベルに設定
rownames(mdDf) <- mdDf$"label"
```


###### b-4.　不要データの削除
感情（label)フィールドは行に設定したので、列データとしては不要なため
削除します。
1列目のフィールドを削除します。

```R:不要データの設定
#感情列(label)を削除
mdDf <- mdDf[, -1] 
```

###### b-5.　コレスポンデンス分析の実行
corresp関数を使用してコレスポンデンス分析を実行します。
nfの値は因子軸の数を指定。今回は２です。

```R:コレスポンデンス分析の実行
#コレスポンデンス分析実施 2次元
corresp_result<-corresp(mdDf,nf=2)
```

###### b-6.　結果の表示
最後に結果を表示します。
parを使って描画サイズなどを変更しようとしましたが、余白のみできて、他はできませんでした。。
最後にplotで図を描画しています。

```R:コレスポンデンス分析の結果表示
# プロットエリアのサイズを指定して描画
par(mai = c(0, 0, 0, 0))  # 余白を設定 (下, 左, 上, 右) の順でインチ単位
#par(pin = c(10, 8))  # プロットエリアのサイズ (横 10 インチ、縦 8 インチ)

# 結果の表示
print(corresp_result)

# 図のプロット
plot(corresp_result, main = "Correspondence Analysis using MASS")
```

#### ⑤. コレスポンデンスの結果確認
　拡張の出力結果を確認します。

 テキスト出力タブでは、Printで出力した結果が確認できます。
 各要素の座標が分かりますね。

 ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3839172/5fc0b16a-2354-fd03-7fa7-4ae1c578cf72.png)

 グラフ出力タブでは、Plotで出力した結果が確認できます。
 フィールド名が長いのでごちゃごちゃしてしますが、
 
 ・POSITIVEの周りには、"カラオケ"や"友達"など楽しそうな単語があります。
 ・NEGATIVEの周りには、"顔"、"ほんま"など。つかれていたのでしょうか。。
 ・NEUTRALの周りには、あまりないですが、"ひと"など、ポジティブ、ネガティブどちらの感情でも使われそうな単語ですね。

 ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3839172/2c9e8e14-2506-984d-c512-50140e31fe85.png)


### 4. まとめ
　いかがでしたでしょうか。全４回にわたり"SPSS Modeler"での日本語テキストマイニングの実装方法を説明させていただきました。
　英語やドイツ語などの外国語であれば"SPSS Modeler Premium"の"Text Analytics"が使用できますが、日本語に関しては残念ながらサポート外となります。
 
 今回ご紹介した拡張ノードを利用した方法をチャレンジしてもらえば、日本語のテキストマイニングも可能ですので、ぜひチャレンジしてみてください。



# 参考

SPSS Modeler ノードリファレンス目次

https://qiita.com/416nishimaki/items/503037195081d3323eee

SPSS Modeler 逆引きストリーム集

https://qiita.com/416nishimaki/items/4bf813e6cba84b2a1008

SPSS funさん記事集

https://qiita.com/spssfun2017

SPSS連載ブログバックナンバー

https://qiita.com/416nishimaki/items/24c054defbe7280bcf0e

SPSSヒモトクブログ

https://www.ibm.com/blogs/solutions/jp-ja/category/bigdata-analytics/spss-modeler-himotoku/