「全力回避フラグちゃん!」チャンネルの動画のk-meansで可視化してみた【クラスタリング】【可視化】

# はじめに

全力回避フラグちゃん! の動画を所有しているデータに基づいて，k-means を用いてクラスタリングしました．
k-means は，教師なし学習の一手法です．今回はクラスタリングされた結果をもとに，そのクラスターに所属する動画がどのような動画であるのかを分析した結果も載せています．


## 注意事項
2021/5/8 18:30時点で取得した情報を利用しています．
出現のカウントは，目視でやっています．基準は過去記事の「全力回避フラグちゃん!」チャンネルの動画をグラフ化するとどうなるのか？【Python】【グラフ化】に書いています．
<b>データを取得及び，データセットを自動作成するプログラムを使用しています．関連リンクのGithub に用意していますので，ご自由にご使用ください</b>

# 用いたデータセット/手法

YouTube Data API のVideos リソースを使用し，2021/5/8 18:30時点において，全力回避フラグちゃん! のチャンネルにアップロードされている全293 本の動画から取得できる情報に加え，実際に動画を視聴して各3フラグの登場をカウント，さらにコラボやShouts，フラグラといった回の情報をラベル付けしています．
データセットの主なカラムは以下の通りです．

|No.|カラム名  |データ型 | 説明 | 
|:-:|:-:|:-:|---|
|1| viewCount | int | 動画の再生回数 |
|2| likeCount |int |動画の高評価数 |
|3| dislikeCount | int | 動画の低評価数 |
|4|commentCount|int|動画のコメント数|
|5|DeadEndCount|int|動画がデッドエンドであれば1，そうでなければ0で表現|
|6|shibouflagCount|int|死亡フラグちゃんが登場していれば1，そうでなければ0で表現|
|7|seizonflagCount|int|生存フラグさんが登場していれば1，そうでなければ0で表現|
|8|renaiflagCount|int|恋愛フラグさんが登場していれば1，そうでなければ0で表現|
|9|videoTime|int|動画時間を秒で表現|
|10|collabo|int|コラボ動画であれば1，そうでなければ0で表現|
|11|story|int|動画がストーリー編であれば1，そうでなければ0で表現|
|12|sub-story|int|動画がサブストーリー編であれば1，そうでなければ0で表現|
|13|flagra|int|動画にフラグラが含まれていれば1，そうでなければ0で表現|
|14|shorts|int|動画がshorts であれば1，そうでなければ0で表現
|15|viewCountLabel|object|動画が100万再生を超えていれば"Yes"，そうでなければ"No"で表現|
|16|vid|object|YouTube が各動画に割り振っているid|
|17|title|object|動画のタイトル|
|18|date|object|動画の公開日|
|19|description|object|動画の概要|

この中で，今回は各動画の再生回数，高評価数，低評価数，コメント数といった基本的な情報と，メタ的な情報として各キャラクターの登場に関する情報で動画をクラスタリングしてみました．上記表のNo. でいうところの「1~4」と「6~8」の7つのカラムを特徴量としています．
これには，各キャラクターの登場と動画の目に見える基本的な情報でクラスタリングするとどうなるのか？という個人的なモチベーションが起因しています．また，k-means + pca を用いた可視化を実施してみたかったというモチベーションもありました．

# プログラムの作成

上記のデータセットと定めた特徴量を用いて，k-means を用いたクラスタリングによる可視化を行うコードが下記です．
まず対象のデータセットを読み込み，今回使用する数値型のカラムのみに絞ります．
そこからさらに，今回使用するカラムのみになるよう不要なカラムを削除し，各カラムの値の範囲を合わせるために値を正規化します．
そこまでが前処理で，前処理が完了したらk-means を実行し，クラスタリングをします．
最後に，2次元平面上に可視化するために，pca を用いて特徴量ベクトルを2次元に変換し，その結果をプロットします．

```python:クラスタリングによる可視化
import sklearn
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt

source_df = pd.read_csv("flag_datasets_20210508.csv")

numerical_df = source_df.select_dtypes(include=['int64'])
numerical_df.drop(['No.'], axis=1, inplace=True)
numerical_df.drop(['videoTime'], axis=1, inplace=True)
numerical_df.drop(['DeadEndCount'], axis=1, inplace=True)
numerical_df.drop(['collabo'], axis=1, inplace=True)
numerical_df.drop(['story'], axis=1, inplace=True)
numerical_df.drop(['sub-story'], axis=1, inplace=True)
numerical_df.drop(['flagra'], axis=1, inplace=True)
numerical_df.drop(['shorts'], axis=1, inplace=True)

import sklearn.preprocessing
scaler = sklearn.preprocessing.MinMaxScaler()
standardization_df = pd.DataFrame(scaler.fit_transform(numerical_df), 
                                  index=numerical_df.index, columns=numerical_df.columns)
standardization_df
std_values = standardization_df.values

from sklearn.cluster import KMeans
k = 4
seed = 1
clusters_videos = KMeans(n_clusters=k, random_state=seed).fit_predict(std_values)
standardization_df['cluster'] = clusters_videos

from sklearn.decomposition import PCA
pca_transformer = PCA(n_components=2)
pca_values = pca_transformer.fit_transform(std_values)

pca_values_df = pd.DataFrame(pca_values)
pca_values_df = pca_values_df.rename(columns={0: "pca_x", 1: "pca_y"})

import matplotlib.pyplot as plt
plt.scatter(pca_values[:, 0], pca_values[:, 1], c=clusters_videos, cmap='gist_rainbow')
plt.title('flag videos', fontsize=14)
plt.show()
```

#可視化の結果

クラスタリングによる可視化の結果は下記です．

![flag_cluster_explain.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/989429/a5fa0ea8-9028-1a5b-c2ce-07152b0842dc.png)

また，表にまとめると以下のようになります．

|cluster|名称※  |動画数 |100万再生を超えた動画数| 説明 | 
|:-:|:-:|:-:|:-:|---|
|0|死亡フラグクラスター|210|55|死亡フラグちゃん単独登場の動画．該当動画数も多く，一番のメインキャラクターが登場する当チャンネルを象徴する基本的な動画の集合．|
|1|オールスタークラスター| 24 | 9 | 一つの動画を除いて，全フラグが登場するオールスター登場の動画の集合． |
|2|デッドオアアライブクラスター |44 |18|6つの動画を除いて，死亡フラグちゃんと生存フラグさんが登場する動画．すべての動画に生存フラグさんが登場している．ほかのクラスターと比較すると，100万再生を超えている動画の割合が4割を超えており，一番割合が高く，人気の確率が高い動画であることが伺える． |
|3|恋愛フラグクラスター |15 | 3 | すべての動画に恋愛フラグさんが登場する動画の集合．死亡フラグちゃんと同時出演はあっても，生存フラグさんと同時出演は含まれない．100万再生を超えている動画の割合が2割丁度で，一番割合が低い．|

<b>※今回の結果をもとに，勝手に命名しました．</b>

前回の[「全力回避フラグちゃん!」チャンネルの動画の人気理由を決定木で可視化してみた【検証】【可視化】](https://qiita.com/mypsychology0/items/36e974d58ad506294a33) では，人気動画の理由を決定木を用いて分析した結果，最上位ノードに生存フラグさんの登場有無がきましたが，全力回避フラグちゃん! の動画では，生存フラグさんの登場有無は動画の100万再生越えを起因する一つのファクターであるのかもしれません．逆に，恋愛フラグさんの登場は100万再生越えに大きな影響を与えなさそうなことがここまでの結果では見えています．

#可視化結果の考察

キャラクターの登場有無を特徴量としているため，クラスタリングの結果も各キャラクターの登場に依存している結果になりました．
具体的には，

- 死亡フラグちゃん
- 全フラグ登場
- 生存フラグさん & 死亡フラグちゃん
- 恋愛フラグさん

といった形に分類されました．まあ，ほかの組み合わせの動画がそもそも少ないため，今回このように4つの集合に分類された形になったのかと思います．再生回数や高評価数といった動画を評価する指標である基本的な情報は，今回の手法ではクラスターを分類するには至りませんでした．

# 簡単なまとめ
- k-means + pca でクラスタリング結果を可視化した
- 見た感じ，4つのクラスターに分かれることが分かった (最適なクラスター数はちゃんと調べる必要がある)
- クラスターの別れ方は，キャラクターの登場に依存した結果になった

# 今後の予定
他にも気になることがあったら，可視化していく予定です．
次は，タイトルや概要欄に使用されている単語の登場回数を調査したり，そこから動画のカテゴリ付けなどをしていく予定です．


# おわりに

ここまで読んでいる人はいないと思いますが，もしいたらまずは，以下のリンクから<b>全力回避フラグちゃん!</b> チャンネルとフラグちゃんのTwitter をフォローしてください．この記事を読むより大切なことです．
大事なことなのでもう一度，<b>チャンネル登録</b>と<b>Twitter のフォロー</b>をよろしくお願いいたします．

# 参考文献
機械学習の手法を実践する際に活用させていただきました．ありがとうございます．
- [仕事ではじめる機械学習 第2版．有賀 康顕，中山 心太，西林 孝　著．2021/04](https://www.oreilly.co.jp/books/9784873119472/)
- [機械学習のための特徴量エンジニアリング――その原理とPythonによる実践，Alice Zheng、Amanda Casari　著．2019/02](https://www.oreilly.co.jp/books/9784873118680/)

# 関連リンク
- YouTube Data API Channels リソース  https://developers.google.com/youtube/v3/docs/channels?hl=ja
- 全力回避フラグちゃん! https://www.youtube.com/channel/UCo_nZN5yB0rmfoPBVjYRMmw/videos
- 株式会社Plott / Plott Inc. https://plott.tokyo/#top
- フラグちゃんのTwitter https://twitter.com/flag__chan
- Github  https://github.com/uky007/flag_analysis