33
25

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

駆け出しエンジニアのカレンダー(~2022/03)Advent Calendar 2021

Day 2

食品を栄養素データに基づいてゼロからクラスタリングしてみた件!

Last updated at Posted at 2021-11-12

Contents

1.はじめに
2.本記事を通してお伝えしたいこと
3.数値解析手法の紹介
4.クラスタリングの仮説
5.k-means法によるクラスタリング
6.クラスタリング結果と考察
7.おわりに
8.APPENDIX

1.はじめに

本記事では、食品を栄養素データに基づいてクラスタリングしてみた過程を、
下記に該当するような、クラスタリングやk-means法を初めて利用する方を対象に紹介します。
なお、著者はシステムエンジニアであり栄養学の専門家では無いため、
システム実装として栄養素を扱うとしたらこういった方法がある、という一例程度にとらえて頂ければ幸いです。

想定ターゲット

  • クラスタリングに触れたことがない初学者の方
  • k-means法に興味があるが触れたことがない初学者の方
  • 栄養素に機械学習を適用して食品を分類することに興味がある方

2.本記事を通してお伝えしたいこと

課題

今回栄養素をクラスタリングをする動機は、
以前、長時間労働による肩凝り・腰痛等の慢性疲労や眼精疲労・免疫力低下といった症状に効く栄養素を
含んでいる食品をレコメンドするサービスの開発を実施しました。
その開発において下記の4点の課題に直面しました。

  • 栄養素⇔食品の定量的な紐づけが難しい

  • 症状⇒栄養素⇒食品のレコメンドロジックを実現しようとしましたが、
    症状⇔栄養素、および栄養素⇔食品間を定量的(機械的)に結びつけることが難しかった

  • 必要栄養素に完璧に紐づく食品が無い

  • レコメンド商品を選定する際に、必要栄養素⇒食品を直接的に紐づようとしても、
    必要栄養素に完全にマッチする食品は無かった

  • 同一の食品のみが、永遠にレコメンドされてしまう

  • レコメンド商品を選定する際に、必要栄養素⇒食品を直接的に紐づけると、
    同一の食品だけを延々と勧め続けてしまった

  • 食品間の類似性に関する、データに基づく数値的な指標があまり無い

解決策

ある症状に対してどの食品を紐づけるかにおいて、完全にマッチする食品はありません。
故に、上述の課題の解決策として、特定の症状に対して、
特定の食品を対応付けるのではなく、食品のグループを対応付けます。
具体的には、下記の方式とします。

  • クラスタリングによって事前に栄養素別の食品グループを定義する
  • 現れた症状に対してどの食品グループをレコメンドするかをあらかじめ対応させておく
  • そのグループの中から食品を選んでお勧めする

本記事で整理すること

そうした背景を踏まえて、本記事では下記について実施した過程を紹介します。

  • 栄養素⇔食品間を定量的(機械的)に結びつけるクラスタリングの手法を見出す
  • 食品のクラスタリングにおけるk-means法の妥当性を検証する
  • 栄養素⇔食品間の関連性に関する情報を得る
  • 健康的な食生活を送るために、どのような食品を組み合わせると
    様々な栄養素をバランス良く摂取できるかを数値的な裏付けを持って示す

3.数値解析手法の紹介

本記事では、栄養素データに基づいて食品を分類することを考えています。
分類には、**教師あり学習のクラス分類(Classification)教師なし学習のクラスタリング(Clustering)**があります。
今回は事前に分類結果の教師データを与えるのではなく、栄養素データの特徴を見出しながら食品のグループを発見していくという教師なし学習であるため、クラスタリングを使用します。
ここからは、クラスタリングの手法について紹介していきます。

クラスタリングとは

  • 機械学習の1種
  • 教師なし学習で行う
  • データをもとに特徴を学習した上で、データ間の類似度に基づいて、データをグループ分けする手法
  • クラスタリングによってできたグループはクラスタと呼ばれる

実際の活用例としては、販売業務などにおいて下記のような活用事例が考えられます。

  • 顧客情報をクラスタリングし、顧客をグループ分けすることで、特定の商品が購入された等の条件を満たした時に、その顧客と同じグループに属する他の顧客にもその商品をレコメンドする
  • 商品情報をクラスタリングし、商品をグループ分けすることで、特定の商品が購入された等の条件を満たした時に、その顧客に対してその商品と同じグループに属する他の商品もレコメンドする

階層クラスタリングと非階層クラスタリング

階層クラスタリング

  • 最も似ている組み合わせから順番に、まとまり(クラスター)にしていく方法
  • 途中過程が階層のように表せ、最終的に樹形図(デンドログラム)ができる
  • 階層的な構造を持つ
  • 樹形図としてグルーピングされるため、
    クラスターを形成した後で自由にクラスタを分けることができる
  • あらかじめクラスターの数を決めておく必要がない
  • 計算量が増大すると処理がしにくくなるため、
    ビッグデータのような膨大なデータのクラスタリングには向いていない

非階層クラスタリング

  • 先ずクラスターの数を決めてしまい、
    そのクラスタ数となるようなデータのグルーピングを計算・検討する手法
  • 異なる性質のものが混ざり合った集団から、互いに似た性質を持つものを集め、クラスターを作る
  • 階層型クラスタリングとの相違点
  • クラスターの数をあらかじめ決めておく必要がある
  • 計算後にクラスター数を増減させ、グルーピングを変更することは困難である
  • 階層的な構造が無いので膨大なデータでも処理が可能なことがメリットで、
    サンプル数が大きいビッグデータを分析する時にも適している
  • 問題点
  • 初期値依存性

このように、対象の少ないデータであれば階層クラスタリング、
ビッグデータであれば非階層クラスタリングと分けて考えておくと良いでしょう。

次に非階層クラスタリングの代表的手法であるk-means法等を説明します。

非階層クラスタリングの代表的なアルゴリズムの紹介

k-means、k-means++、x-meansについて

非階層クラスタリングにはアルゴリズムが複数ありますが、
その中でも代表的なアルゴリズムとしては、k-means、k-means++、x-meansなどが挙げられます。
k-means法だけでなく、k-means法の初期値依存という問題に対応したk-means++という手法や、初期値依存の問題に対応するだけでなく、さらにクラスタ数まで自動で推定してくれるx-meansという手法もあります。
以下では、各々のアルゴリズムの特徴についてそれぞれ紹介します。

k-means法とは

  • 非階層型クラスタリングのアルゴリズム
  • 下のFig.1のように、まずデータを適当なクラスターに分けた後、
    クラスターの平均を用いてうまくデータがわかれるように調整させていく
  • クラスターの平均を用い、与えられたクラスタ数k個に分類する
  • 重心が変化しなくなるまで、繰り返し計算する
  • アルゴリズムの中では比較的シンプルな構造のため扱いやすい
  • 任意の指定のk個のクラスターを作成することから、k-means法、k点平均法、k-平均法と呼ばれている

k-means.PNG
Fig.1

k-means法の問題点(初期値依存)について

k-means法の一つの短所として、初期値(初期に選択される核となるk個のサンプル)依存性があります。

  • 問題点
  • 同じデータを距離等を同じ条件にして計算しても、初期値が異なるだけで、結果が大きく異なる
  • 最初にランダムにクラスターを割り振るため、その初期値によって精度が変わってしまい、最適とはかけ離れたクラスタリングがなされてしまう可能性がある
  • 初期値によって結果が収束するまでの時間も多く要する
  • 対処方法
  • 良いクラスターを得るためには、初期値を変えて何回か分析を実施し、
    平均クラスター内距離が最小になる初期値を選択するなど、最適初期値での結果を採用する

k-meansは初期値依存という問題を抱えているため、
その問題点の克服を試みているk-means++というアルゴリズムが開発されています。

k-means++とは

  • k-meansの初期値依存問題の克服を目指したアルゴリズム
  • 初期のクラスタの中心同士は離れていた方が良いという考え方に基づいて設計されており、
    初期のクラスターはデータ点間の距離に応じて確率的に割り振る
  • 初期のクラスター中心点をデータ点間の距離に基づいて確率的に決定することで、
    初期値依存問題の解決を試みている

x-meansとは

  • k-meansの拡張アルゴリズム
  • k-meansの逐次繰り返しとBICによるクラスターの分割処理停止基準を用いることによって、
    最適なクラスター数を決定する
  • k-meansとの差分
  • クラスター数kを自動決定する
  • k-meansをデータ数が多くても高速に動くようなアルゴリズムに改善している
  • x-meansではk-meansを再帰的に呼び出し利用をしている
  • k-meansの欠点である初期値依存性を継承していて、クラスターは計算毎に少しずつ変わる。
    しかし、クラスターサイズは安定しているので最適なクラスター数の目安にはなる
  • 情報が全く無い時に、発見的な方法によらず、
    k-meansの凡そ2倍強の計算量で最適なクラスター数を求められる

本記事では、k-means、k-means++を採用

k-meansと階層型の特徴を考えた時に、
実際に今回はk-meansか階層型のどちらのクラスタリングを使うかということを検討します。
本記事では、クラスタリング対象の計算する食品の量(個数)が多すぎて、
且つパラメーターである栄養素の個数も60個で膨大です。
このように食品量と栄養素の数が膨大なので
計算量の観点で、計算量が少なくて済む非階層型クラスタリングの方が適しており、
そのアルゴリズムの中では比較的シンプルな構造のため扱いやすく**計算量が少ないk-means、k-means++**を最終的に選定して、クラスタリングを実行します。

4.クラスタリングの仮説

本記事では、食品の個数を59個、栄養素の種類を60種類としています。
下記のサイトを参考に、主要な食材・食品、および主要な栄養素を選定しました。

日本食品標準成分表2020年版(八訂)

食品の一覧

こむぎ 食パン,こむぎ うどん ゆで,こむぎ 即席中華めん 油揚げ味付け,こむぎ 中華スタイル即席カップめん 油揚げ 焼きそば,こむぎ マカロニ・スパゲッティ ゆで,こめ 水稲めし 玄米,こめ 水稲めし 精白米 うるち米,こめ もち米製品 もち,そば ゆで,さつまいも 塊根 皮むき 焼き,じゃがいも 塊茎 蒸し,だいず 絹ごし豆腐,だいず 糸引き納豆,キャベツ 結球葉 生,きゅうり 果実 生,たまねぎ類 たまねぎ りん茎 生,トマト 果実 生,ブロッコリー 花序 ゆで,レタス 土耕栽培 結球葉 生,いちご 生,うんしゅうみかん じょうのう 普通 生,パインアップル 生,バナナ 生,メロン 温室メロン 生,りんご 皮むき 生,生しいたけ 菌床栽培 生,ぶなしめじ 生,湯通し塩蔵わかめ 塩抜き,まあじ 皮つき、フライ,べにざけ 焼き,まさば 焼き,あさり 生,しじみ 生,ほたてがい 生,和牛肉 もも 皮下脂肪なし 焼き,乳用肥育牛肉 ヒレ 赤肉 焼き,交雑牛肉 リブロース 脂身つき 焼き,ぶた 大型種肉 ロース 脂身つき 焼き,ぶた 大型種肉 ヒレ 赤肉 とんかつ,ぶた ロースハム,ぶた ウインナーソーセージ,若鶏肉 むね 皮なし 焼き,若鶏肉 もも 皮なし 焼き,若鶏肉 もも 皮なし ゆで,鶏卵 全卵 生,普通牛乳,ヨーグルト 全脂無糖,プロセスチーズ,植物油脂類 オリーブ油,植物油脂類 ごま油,ポテトチップス,ミルクチョコレート,清酒 普通酒,ビール 淡色,ぶどう酒 赤,せん茶 浸出液,スポーツドリンク,炭酸飲料類 果実色飲料,コーラ

栄養素の一覧

たんぱく質,脂 質,炭水化物,食物繊維総量,水 分,アミノ酸組成によるたんぱく質,トリアシルグリセロール当量,飽和脂肪酸,一価不飽和脂肪酸,多価不飽和脂肪酸,コレステロール,利用可能炭水化物単糖当量,水溶性食物繊維,不溶性食物繊維,灰 分,ナトリウム,カリウム,カルシウム,マグネシウム,リン,鉄,亜鉛,銅,マンガン,ヨウ素,セレン,クロム,モリブデン,レチノール,α0カロテン,β0カロテン,β0クリプトキサンチン,β0カロテン当量,レチノール活性当量,ビタミンD,α0トコフェロール,β0トコフェロール,γ0トコフェロール,δ0トコフェロール,ビタミンK,ビタミンB1,ビタミンB2,ナイアシン,ビタミンB6,ビタミンB12,葉酸,パントテン酸,ビオチン,ビタミンC,食塩相当量,アルコール,硝酸イオン,テオブロミン,カフェイン,タンニン,ポリフェノール,酢酸,調理油,有機酸

仮説

現時点の想定としては、各食品がどの栄養素を主として含んでいるかに応じて、
炭水化物豊富群、タンパク質豊富群、脂質多め群、カロリー高め群のような、クラスターに分かれると考えられます。
具体的には以下の表のように14個のクラスターに分類されると想定しています。
こちらのクラスター分類は、文部科学省が公開している日本食品標準成分表2020年版(八訂)に記載されている食品群に基づく標準的な食品の分類になります。

想定する食品の分類表

cluster番号 食品数 食品
0 9 食パン、うどん、即席中華麺、カップ焼きそば、マカロニ・スパゲッティ、玄米、うるち米、もち、そば
1 2 さつま芋、じゃがいも
2 2 豆腐、納豆
3 6 キャベツ、きゅうり、玉ねぎ、トマト、ブロッコリー、レタス
4 6 いちご、みかん、パインアップル、バナナ、メロン、りんご
5 2 しいたけ、ぶなしめじ
6 1 わかめ
7 6 あじフライ、焼き鮭、焼きサバ、あさり、しじみ、ホタテ貝
8 9 牛もも、牛ヒレ、牛リブロース、豚ロース、ヒレカツ、ロースハム、ウインナーソーセージ、鶏むね、鶏もも
9 1 鶏卵
10 3 牛乳、ヨーグルト、チーズ
11 2 オリーブ油、ごま油
12 2 ポテトチップス、チョコレート
13 7 清酒、ビール、ぶどう酒、せん茶、スポーツドリンク、炭酸飲料、コーラ

5.k-means法によるクラスタリング

ソースコード

本記事のクラスタリングはPythonを利用して実行します。
早速Pythonを使用してクラスタリングのソースコードを書いて実行していきます。

最初に、使用するライブラリなどをインポートします。

ライブラリのインポートなど
# 基本のライブラリを読み込む
import pandas as pd # データフレームワーク処理のライブラリ
import numpy as np
import sklearn #機械学習のライブラリ
from sklearn.cluster import KMeans # Scikit learnのClusterからKMeansをimport
from sklearn.decomposition import PCA #主成分分析 PCA
from sklearn import preprocessing
from sklearn.preprocessing import StandardScaler
%matplotlib inline 
import matplotlib as mpl
import matplotlib.pyplot as plt # 図やグラフを図示するためのライブラリ
from matplotlib import pylab as plt # グラフ描画
from matplotlib.pylab import rcParams
plt.rcParams['font.size'] = 18 # グラフの基本フォントサイズの設定
mpl.rcParams['font.family'] = ['serif']
import seaborn as sns
np.set_printoptions(threshold=100)
pd.set_option('display.max_rows', 100)
pd.set_option('display.max_columns', 20)
noc = 15 #クラスター数 Number Of Clusters
# noc = 10 #クラスター数 Number Of Clusters

次に、様々な食品の栄養素データが記載されている下記のcsvファイルをインポートします。
このcsvファイルは、文部科学省が公開している日本食品標準成分表2020年版(八訂)を参考に、
主要な食品を抜粋して作成したものであります。

食品の含有栄養素データのcsvファイル
食品群,索引番号,食品名,エネルギーkcal,たんぱく質,   ,炭水化物,食物繊維総量,飽和脂肪酸,一価不飽和脂肪酸,多価不飽和脂肪酸,コレステロール,ナトリウム,カリウム,カルシウム,マグネシウム,,亜鉛,β0カロテン,ビタミンD,ビタミンB1,ビタミンB6,ビタミンB12,葉酸,ビタミンC,食塩相当量,カフェイン,   ,アミノ酸組成によるたんぱく質,トリアシルグリセロール当量,利用可能炭水化物単糖当量,水溶性食物繊維,不溶性食物繊維,   ,リン,,マンガン,ヨウ素,セレン,クロム,モリブデン,レチノール,α0カロテン,β0クリプトキサンチン,β0カロテン当量,レチノール活性当量,α0トコフェロール,β0トコフェロール,γ0トコフェロール,δ0トコフェロール,ビタミンK,ビタミンB2,ナイアシン,パントテン酸,ビオチン,アルコール,硝酸イオン,テオブロミン,タンニン,ポリフェノール,酢酸,調理油,有機酸
1,26,'こむぎ 食パン',264,9.3,4.4,46.7,2.3,1.9,1.15,0.87,0,500,97,29,20,0.6,0.8,2,0,0.07,0.03,0,32,0,1.3,0,38.0,7.5,4.1,49.1,0.4,1.9,1.6,83,0.11,0.24,1,24,1,18,0,0,0,2,0,0.5,0.1,0.7,0,0,0.04,1.2,0.47,2.4,0,0,0,0,0,0,0,0
1,38,'こむぎ うどん ゆで',105,2.6,0.4,21.6,0.8,0.09,0.04,0.2,0,120,9,6,6,0.2,0.1,0,0,0.02,0.01,0,2,0,0.3,0,75.0,2.2,0.3,21.4,0.2,0.6,0.4,18,0.04,0.12,0,2,1,2,0,0,0,0,0,0.1,0.1,0,0,0,0.01,0.2,0.13,0.3,0,0,0,0,0,0,0,0
1,54,'こむぎ 即席中華めん 油揚げ味付け',445,10.1,16.7,63.5,2.5,7.31,6.02,2.25,7,2500,260,430,29,1.0,0.5,0,0,1.46,0.06,0,12,0,6.4,0,2.0,8.8,16.3,63.0,1.6,0.9,7.7,110,0.13,0.82,0,0,0,0,0,0,0,0,0,3.1,0.3,3.1,2.5,1,1.67,1.0,0.41,0,0,0,0,0,0,0,0,0
1,58,'こむぎ 中華スタイル即席カップめん 油揚げ 焼きそば',436,8.4,18.9,58.1,2.4,5.36,6.92,2.86,1,1500,190,190,28,1.1,0.4,75,0,0.56,0.04,0,13,1,3.8,0,10.0,0,15.8,0,0.9,1.5,4.6,74,0.13,0.69,0,0,0,0,0,6,0,78,7,2.2,0.4,2.4,2.0,14,0.72,0.8,0.40,0,0,0,0,0,0,0,0,0
1,64,'こむぎ マカロニ・スパゲッティ ゆで',165,5.4,0.9,32.0,1.7,0.21,0.08,0.47,0,460,14,8,20,0.7,0.7,0,0,0.06,0.02,0,5,0,1.2,0,60.5,4.9,0.8,31.2,0.5,1.2,1.2,52,0.14,0.35,0,32,1,12,0,0,0,0,0,0.1,0.1,0,0,0,0.03,0.6,0.28,1.6,0,0,0,0,0,0,0,0
1,90,'こめ 水稲めし 玄米',165,2.8,1.0,35.6,1.4,0.23,0.3,0.33,0,1,95,7,49,0.6,0.8,0,0,0.16,0.21,0,10,0,0,0,60.0,2.4,0.9,35.1,0.2,1.2,0.6,130,0.12,1.04,0,1,0,34,0,0,0,0,0,0.5,0,0.1,0,0,0.02,2.9,0.65,2.5,0,0,0,0,0,0,0,0
1,93,'こめ 水稲めし 精白米 うるち米',168,2.5,0.3,37.1,0.3,0.1,0.07,0.1,0,1,29,3,7,0.1,0.6,0,0,0.02,0.02,0,3,0,0,0,60.0,2.0,0.3,38.1,0,0.3,0.1,34,0.10,0.35,0,1,0,30,0,0,0,0,0,0,0,0,0,0,0.01,0.2,0.25,0.5,0,0,0,0,0,0,0,0
1,129,'こめ もち米製品 もち',234,4.0,0.6,50.8,0.5,0.17,0.11,0.18,0,0,32,3,6,0.1,0.9,0,0,0.03,0.03,0,4,0,0,0,44.5,3.6 ,0.5,50.0 ,0,0.5,0.1,22,0.13,0.58,0,2,0,56,0,0,0,0,0,0,0,0,0,0,0.01,0.2,0.34,0.6,0,0,0,0,0,0,0,0
1,141,'そば ゆで',132,4.8,1.0,26.0,2.0,0.21,0.22,0.42,0,2,34,9,27,0.8,0.4,0,0,0.05,0.04,0,8,0,0,0,68.0,3.9,0.9,27,0.5,1.5,0.2,80,0.10,0.38,0,12,2,11,0,0,0,0,0,0.1,0,0.8,0,0,0.02,0.5,0.33,2.7,0,0,0,0,0,0,0,0
2,173,'さつまいも 塊根 皮むき 焼き',163,1.4,0.2,39.0,3.5,0.03,0,0.03,0,13,540,34,23,0.7,0.2,0,0,0.12,0.33,0,47,23,0,0,58.1,1.2,0.1,36.7,1.1,2.4,1.3,55,0.20,0.32,0,0,0,0,0,0,0,6,1,1.3,0,0,0,0,0.06,1.0,1.30,0,0,0,0,0,0,0,0,0.5
2,192,'じゃがいも 塊茎 蒸し',84,1.5,0.1,19.7,1.8,0.01,0,0.02,0,1,330,2,20,0.3,0.2,0,0,0.05,0.18,0,22,15,0,0,78.1,1.2,0,15.7,0.6,1.2,0.6,23,0.08,0.13,0,0,0,0,0,0,0,0,0,0.1,0,0,0,0,0.02,0.8,0.52,0,0,0,0,0,0,0,0,0.5
2,194,'じゃがいも フライドポテト',237,2.9,10.6,32.4,3.1,0.83,6.28,2.74,0,2,660,4,35,0.8,0.4,0,0,0.12,0.35,0,35,40,0,0,52.9,2.3,10.3,27.5,1.0,2.1,1.2,48,0.15,0.19,0,0,0,0,0,0,0,0,0,1.5,0.1,5.9,1.1,18,0.06,1.5,0.71,0,0,0,0,0,0,0,0,0
4,293,'だいず 絹ごし豆腐',56,4.9,3.0,2.0,0.3,0.48,0.56,1.58,0,14,150,57,55,0.8,0.5,0,0,0.10,0.06,0,11,0,0,0,89.4,4.8,2.7,0.9,0.1,0.2,0.7,81,0.15,0.31,0,0,0,0,0,0,0,0,0,0.1,0,2.1,0.9,12,0.04,0.2,0.09,0,0,0,0,0,0,0,0,0
4,311,'だいず 糸引き納豆',200,16.5,10.0,12.1,6.7,1.45,2.21,5.65,0,2,660,90,100,3.3,1.9,0,0,0.07,0.24,0,120,0,0,0,59.5,14.2,9.7,0.3,2.3,4.4,1.9,190,0.61,0,0,16,1,290,0,0,0,0,0,0.5,0.2,5.9,3.3,600,0.56,1.1,3.60,18.2,0,0,0,0,0,0,0,0
6,455,'キャベツ 結球葉 生',23,1.3,0.2,5.2,1.8,0.02,0.01,0.02,0,5,200,43,14,0.3,0.2,49,0,0.04,0.11,0,78,41,0,0,92.7,0.9,0.1,3.5,0.4,1.4,0.5,27,0.02,0.16,0,0,1,4,0,0,1,50,4,0.1,0,0,0,78,0.03,0.2,0.22,1.6,0,0.1,0,0,0,0,0,0.1
6,460,'きゅうり 果実 生',14,1.0,0.1,3.0,1.1,0.01,0,0.01,0,1,200,26,15,0.3,0.2,330,0,0.03,0.05,0,25,14,0,0,95.4,0.7,0,2.0,0.2,0.9,0.5,36,0.11,0.07,1,1,1,4,0,1,0,330,28,0.3,0,0,0,34,0.03,0.2,0.33,1.4,0,0,0,0,0,0,0,0.3
6,547,'たまねぎ類 たまねぎ りん茎 生',37,1.0,0.1,8.8,1.6,0.01,0,0.03,1,2,150,21,9,0.2,0.2,1,0,0.03,0.16,0,16,8,0,0,89.7,0.6,0,7.0,0.6,1.0,0.4,33,0.05,0.15,1,1,0,1,0,0,0,1,0,0.1,0,0,0,0,0.01,0.1,0.19,0.6,0,0,0,0,0,0,0,0.2
6,580,'トマト 果実 生',19,0.7,0.1,4.7,1.0,0.02,0.01,0.03,0,3,210,7,9,0.2,0.1,540,0,0.05,0.08,0,22,15,0,0,94.0,0.5,0.1,3.1,0.3,0.7,0.5,26,0.04,0.08,0,1,0,2,0,4,0,540,45,0.9,0,0.2,0,4,0.02,0.7,0.17,2.3,0,0,0,0,0,0,0,0.4
6,676,'ブロッコリー 花序 ゆで',27,3.5,0.4,4.3,3.7,0.05,0.04,0.08,0,14,180,33,17,0.7,0.3,770,0,0.06,0.12,0,120,54,0,0,91.3,2.4,0.2,1.2,0.8,2.9,0.5,66,0.06,0.17,0,0,0,0,0,0,5,770,64,1.7,0,0.4,0,150,0.09,0.4,0.78,0,0,0,0,0,0,0,0,0
6,735,'レタス 土耕栽培 結球葉 生',12,0.6,0.1,2.8,1.1,0.01,0,0.03,0,2,200,19,8,0.3,0.2,240,0,0.05,0.05,0,73,5,0,0,95.9,0.5,0,1.7,0.1,1.0,0.5,22,0.04,0.13,1,0,0,0,0,0,0,240,20,0.3,0,0.2,0,29,0.03,0.2,0.20,1.2,0,0.1,0,0,0,0,0,0
7,763,'いちご 生',34,0.9,0.1,8.5,1.4,0.01,0.01,0.05,0,0,170,17,13,0.3,0.2,17,0,0.03,0.04,0,90,62,0,0,90.0,0.6,0.1,6.1,0.5,0.9,0.5,31,0.05,0.20,1,0,0,9,0,0,1,18,1,0.4,0,0.2,0,0,0.02,0.4,0.33,0.8,0,0,0,0,0,0,0,0.8
7,786,'うんしゅうみかん じょうのう 普通 生',46,0.7,0.1,12.0,1.0,0.01,0.02,0.01,0,1,150,21,11,0.2,0.1,180,0,0.10,0.06,0,22,32,0,0,86.9,0.4,0,9.2,0.5,0.5,0.3,15,0.03,0.07,0,0,0,0,0,0,1700,1000,84,0.4,0,0,0,0,0.03,0.3,0.23,0.5,0,0,0,0,0,0,0,0
7,872,'パインアップル 生',51,0.6,0.1,13.4,1.5,0.01,0.01,0.03,0,0,150,10,14,0.2,0.1,30,0,0.08,0.08,0,11,27,0,0,85.5,0.4,0.1,11.3,0.1,1.4,0.4,9,0.11,0.76,0,0,0,0,0,0,1,30,3,0,0,0,0,0,0.02,0.2,0.28,0.2,0,0,0,0,0,0,0,1.0
7,881,'バナナ 生',86,1.1,0.2,22.5,1.1,0.07,0.02,0.04,0,0,360,6,32,0.3,0.2,42,0,0.05,0.38,0,26,16,0,0,75.4,0.7,0.1,19.4,0.1,1.0,0.8,27,0.09,0.26,0,1,0,7,0,28,0,56,5,0.5,0,0,0,0,0.04,0.7,0.44,1.4,0,0,0,0,0,0,0,0.7
7,904,'メロン 温室メロン 生',42,1.1,0.1,10.3,0.5,0.03,0,0.04,0,7,340,8,13,0.3,0.2,32,0,0.06,0.10,0,32,18,0,0,87.8,0.7,0.1,9.6,0.2,0.3,0.7,21,0.05,0.04,0,2,1,4,0,0,3,33,3,0.2,0,0.1,0,0,0.02,0.5,0.19,0.9,0,0,0,0,0,0,0,0
7,917,'りんご 皮むき 生',57,0.1,0.2,15.5,1.4,0.01,0,0.03,0,0,120,3,3,0.1,0,12,0,0.02,0.04,0,2,4,0,0,84.1,0.1,0,12.4,0.4,1.0,0.2,12,0.05,0.02,0,0,1,0,0,0,7,15,1,0.1,0,0,0,0,0,0.1,0.03,0.5,0,0,0,0,0,0,0,0.5
8,937,'生しいたけ 菌床栽培 生',19,3.0,0.3,5.7,4.2,0.04,0.01,0.15,0,1,280,1,15,0.3,1.0,0,0.4,0.13,0.21,0,44,0,0,0,90.3,1.9,0.2,0.6,0.4,3.8,0.6,87,0.09,0.22,0,6,1,4,0,0,0,0,0,0,0,0,0,0,0.20,3.1,1.05,7.3,0,0,0,0,0,0,0,0.2
8,947,'ぶなしめじ 生',18,2.7,0.6,5.0,3.7,0.05,0.02,0.17,0,3,380,1,11,0.4,0.5,0,0.6,0.16,0.08,0,28,0,0,0,90.8,1.6,0.2,1.3,0.3,3.4,0.9,100,0.06,0.12,2,3,0,5,0,0,0,0,0,0,0,0,0,0,0.16,6.6,0.86,9.9,0,0,0,0,0,0,0,0
9,1024,'湯通し塩蔵わかめ 塩抜き',11,1.7,0.4,3.1,3.0,0.03,0.02,0.17,0,540,12,42,19,0.5,0.2,250,0,0.01,0,0,11,0,1.4,0,93.3,1.4,0.2,0,0,0,1.5,31,0.01,0.03,780,0,1,0,0,0,0,250,21,0.1,0,0,0,100,0.01,0,0.12,1.8,0,0,0,0,0,0,0,0
10,1034,'まあじ 皮つき、フライ',276,20.1,18.2,7.9,0,2.25,9.23,4.75,80,160,330,100,35,0.8,1.2,0,7.0,0.12,0.15,7.5,10,0,0.4,0,52.3,16.2,17.0,8.5,0,0,1.4,250,0.08,0.11,0,0,0,0,16,0,1,1,16,3.4,0,5.9,0.1,23,0.15,4.6,0.53,0,0,0,0,0,0,0,0,0
10,1191,'べにざけ 焼き',177,28.5,6.0,0.1,0,1.06,2.29,1.30,76,72,490,16,39,0.5,0.7,0,38.4,0.27,0.39,3.8,15,2,0.2,0,63.4,23.6,4.9,0,0,0,2.0,340,0.08,0.01,0,0,0,0,35,0,0,0,35,1.8,0,0,0,0,0.22,7.2,1.49,0,0,0,0,0,0,0,0,0
10,1197,'まさば 焼き',318,25.2,22.4,0.4,0,5.87,6.68,3.84,79,120,370,10,34,1.6,1.4,0,4.9,0.30,0.54,21.9,13,0,0.3,0,54.1,21.4,17.1,0,0,0,1.3,280,0.16,0.01,24,21,6,1,34,0,0,0,34,2.1,0,0,0,4,0.37,13.4,0.79,8.2,0,0,0,0,0,0,0,0
10,1332,'あさり 生',30,6.0,0.3,0.4,0,0.02,0.01,0.04,40,870,140,66,100,3.8,1.0,21,0,0.02,0.04,52.4,11,1,2.2,0,90.3,4.5,0.1,0,0,0,3.0,85,0.06,0.10,55,38,4,9,2,1,0,22,4,0.4,0,0,0,0,0.16,1.4,0.39,22.7,0,0,0,0,0,0,0,0
10,1349,'しじみ 生',64,7.5,1.4,4.5,0,0.24,0.14,0.19,62,180,83,240,10,8.3,2.3,97,0.2,0.02,0.10,68.4,26,2,0.4,0,86.0,5.7,0.6,0,0,0,1.2,120,0.41,2.78,0,0,0,0,25,13,1,100,33,1.7,0,0,0,2,0.44,1.5,0.53,0,0,0,0,0,0,0,0,0
10,1363,'ほたてがい 生',72,13.5,0.9,1.5,0,0.18,0.09,0.15,33,320,310,22,59,2.2,2.7,150,0,0.05,0.07,11.4,87,3,0.8,0,82.3,9.8,0.4,0,0,0,1.8,210,0.13,0.12,0,0,0,0,10,1,0,150,23,0.9,0,0,0,1,0.29,1.7,0.66,0,0,0,0,0,0,0,0,0
11,1469,'和牛肉 もも 皮下脂肪なし 焼き',333,27.7,22.7,0.5,0,7.64,11.28,0.67,100,50,350,5,25,3.8,6.3,0,0,0.09,0.35,1.9,7,1,0.1,0,49.5,23.4,20.5,0,0,0,1.1,190,0.10,0,0,19,1,1,0,0,0,0,0,0.4,0,0,0,10,0.24,6.6,1.18,2.9,0,0,0,0,0,0,0,0
11,1511,'乳用肥育牛肉 ヒレ 赤肉 焼き',259,27.2,15.2,0.4,0,5.74,6.70,0.54,74,74,440,5,28,3.5,6.0,1,0,0.16,0.45,4.9,10,0,0.2,0,56.3,24.3,13.6,0,0,0,1.3,230,0.12,0.01,1,19,1,1,3,0,0,1,3,0.3,0,0,0,6,0.35,6.2,1.16,3.9,0,0,0,0,0,0,0,0
11,1513,'交雑牛肉 リブロース 脂身つき 焼き',627,14.5,60.1,0.2,0,21.12,32.78,1.71,100,47,190,3,12,1.5,3.8,2,0,0.06,0.20,1.8,14,0,0.1,0,26.4,12.3,58.2,0,0,0,0.6,100,0.04,0,1,11,1,1,0,0,1,2,0,0.7,0,0.1,0,10,0.11,3.3,0.50,1.8,0,0,0,0,0,0,0,0
11,1598,'ぶた 大型種肉 ロース 脂身つき 焼き',328,26.7,22.7,0.3,0,9.32,9.31,2.54,76,52,400,6,29,0.4,2.2,0,0.1,0.90,0.33,0.5,1,1,0.1,0,49.1,22.6,22.1,0,0,0,1.2,250,0.07,0.01,2,29,2,1,2,0,0,0,2,0.1,0,0,0,3,0.21,9.2,1.19,5.2,0,0,0,0,0,0,0,0
11,1618,'ぶた 大型種肉 ヒレ 赤肉 とんかつ',388,25.1,25.3,14.9,0.9,2.72,14.46,5.82,71,140,440,17,33,1.3,2.7,7,0.3,1.09,0.33,0.6,6,1,0.4,0,33.3,21.3,24.0,15.6,0.2,0.7,1.4,260,0.12,0.15,0,30,0,6,3,0,0,7,3,4.1,0,9.3,0.2,32,0.32,7.1,1.16,4.6,0,0,0,0,0,0,0,0
11,1655,'ぶた ロースハム',196,16.5,13.9,1.3,0,4.99,5.67,1.38,40,1000,260,10,19,0.5,1.1,0,0.6,0.60,0.23,0.4,2,50,2.5,0,65.0,13.6,12.6,0,0,0,3.3,340,0.07,0,0,0,0,0,0,0,0,0,0,0.3,0,0,0,3,0.12,6.6,0.57,0,0,0,0,0,0,0,0,0
11,1664,'ぶた ウインナーソーセージ',321,13.2,28.5,3.0,0,10.11,12.65,3.57,57,730,180,7,13,0.8,1.4,0,0.5,0.26,0.10,1.1,1,10,1.9,0,53.0,10.8,27.5,0,0,0,2.3,190,0.07,0,0,0,0,0,0,0,0,0,0,0.3,0,0.1,0,1,0.13,3.6,0.72,0,0,0,0,0,0,0,0,0
11,1711,'若鶏肉 むね 皮なし 焼き',195,38.8,3.3,0.1,0,0.78,1.22,0.65,120,73,570,7,47,0.5,1.1,0,0.1,0.14,0.66,0.3,18,4,0.2,0,57.6,32.5,2.8,0,0,0,1.7,340,0.04,0.01,0,29,1,4,14,0,0,0,14,0.5,0,0.1,0,29,0.18,18.4,2.58,5.3,0,0,0,0,0,0,0,0
11,1717,'若鶏肉 もも 皮なし 焼き',161,25.5,5.7,0,0,1.41,2.14,0.75,120,81,380,7,29,0.9,2.6,0,0,0.14,0.37,0.4,10,3,0.2,0,68.1,21.5,4.5,0,0,0,1.2,220,0.06,0.01,0,0,0,0,13,0,0,0,13,0.3,0,0,0,29,0.23,6.7,1.33,0,0,0,0,0,0,0,0,0
11,1718,'若鶏肉 もも 皮なし ゆで',155,25.1,5.2,0,0,1.36,1.98,0.69,120,56,260,10,25,0.8,2.2,0,0,0.12,0.36,0.3,8,2,0.1,0,69.1,21.1,4.2,0,0,0,0.9,190,0.05,0.01,0,0,0,0,14,0,0,0,14,0.3,0,0,0,25,0.18,5.3,0.99,0,0,0,0,0,0,0,0,0
12,1744,'鶏卵 全卵 生',151,12.3,10.3,0.3,0,2.84,3.69,1.66,420,140,130,51,11,1.8,1.3,3,1.8,0.06,0.08,0.9,43,0,0.4,0,76.1,10.6,8.6,0.3,0,0,1.0,180,0.08,0.02,17,32,0,5,140,0,28,17,150,1.0,0,0.6,0,13,0.43,0.1,1.45,25.4,0,0,0,0,0,0,0,0
13,1762,'普通牛乳',67,3.3,3.8,4.8,0,2.33,0.87,0.12,12,41,150,110,10,0.02,0.4,6,0.3,0.04,0.03,0.3,5,1,0.1,0,87.4,2.9,3.5,4.7,0,0,0.7,93,0.01,0,16,3,0,4,38,0,0,6,38,0.1,0,0,0,2,0.15,0.1,0.55,1.8,0,0,0,0,0,0,0,0
13,1784,'ヨーグルト 全脂無糖',62,3.6,3.0,4.9,0,1.83,0.71,0.10,12,48,170,120,12,0,0.4,3,0,0.04,0.04,0.1,11,1,0.1,0,87.7,3.2,2.8,3.9,0,0,0.8,100,0.01,0,17,3,0,4,33,0,0,3,33,0.1,0,0,0,1,0.14,0.1,0.49,2.5,0,0,0,0,0,0,0,0
13,1805,'プロセスチーズ',339,22.7,26.0,1.3,0,16.00,6.83,0.56,78,1100,60,630,19,0.3,3.2,0,0,0.03,0.01,3.2,27,0,2.8,0,45.0,21.1,24.7,0.1,0,0,5.0,730,0.08,0,0,0,0,0,240,0,0,230,260,1.1,0,0,0,2,0.38,0.1,0.14,0,0,0,0,0,0,0,0,1.3
14,1820,'植物油脂類 オリーブ油',921,0,100.0,0,0,13.29,74.04,7.24,0,0,0,0,0,0,0,180,0,0,0,0,0,0,0,0,0,0,98.9,0,0,0,0,0,0,0,0,0,0,0,0,0,5,180,15,7.4,0.2,1.2,0.1,42,0,0,0,0,0,0,0,0,0,0,0,0
14,1821,'植物油脂類 ごま油',921,0,100.0,0,0,15.04,37.59,41.19,0,0,0,1,0,0.1,0,0,0,0,0,0,0,0,0,0,0,0,98.1,0,0,0,0,1,0.01,0,0,1,1,0,0,0,0,0,0,0.4,0,43.7,0.7,5,0,0.1,0,0,0,0,0,0,0,0,0,0
15,1968,'ポテトチップス',554,4.7,35.2,54.7,4.2,3.86,14.47,14.41,0,400,1200,17,70,1.7,0.5,0,0,0.26,0,0,70,15,1.0,0,2.0,4.4,34.2,0,1.1,3.1,3.4,100,0.21,0.40,260,0,3,10,0,0,0,0,0,6.2,0.3,0.8,0.1,0,0.06,4.3,0.94,1.6,0,0,0,0,0,0,0,0
15,1982,'ミルクチョコレート',558,6.9,34.1,55.8,3.9,19.88,10.38,1.08,19,64,440,240,74,2.4,1.6,35,1.0,0.19,0.11,0,18,0,0.2,0,0.5,5.8,32.8,59.3,1.0,2.9,1.8,240,0.55,0.41,19,6,24,11,63,4,0,37,66,0.7,0,6.5,0.4,6,0.41,1.2,1.56,7.6,0,0,0.2,0,0.7,0,0,0
16,1990,'清酒 普通酒',109,0.4,0,4.9,0,0,0,0,0,2,5,3,1,0,0.1,0,0,0,0.07,0,0,0,0,0,82.4,0.3,0,2.5,0,0,0,7,0,0.16,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,12.3,0,0,0,0,0,0,0
16,1995,'ビール 淡色',40,0.3,0,3.1,0,0,0,0,0,3,34,3,7,0,0,0,0,0,0.05,0.1,7,0,0,0,92.8,0.2,0,0,0,0,0.1,15,0,0.01,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0.02,0.8,0.08,0.9,3.7,0,0,0,0,0,0,0.1
16,2000,'ぶどう酒 赤',73,0.2,0,1.5,0,0,0,0,0,2,110,7,9,0.4,0,0,0,0,0.03,0,0,0,0,0,88.7,0,0,0.2,0,0,0.3,13,0.02,0.15,0,0,2,1,0,0,0,0,0,0,0,0,0,0,0.01,0.1,0.07,1.9,9.3,0,0,0,0,0,0,0
16,2026,'せん茶 浸出液',2,0.2,0,0.2,0,0,0,0,0,3,27,3,2,0.2,0,0,0,0,0.01,0,16,6,0,0.02,99.4,0,0,0,0,0,0.1,2,0.01,0.31,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.05,0.2,0.04,0.8,0,0,0,0.07,0,0,0,0
16,2035,'インスタントコーヒー',288,14.7,0.3,56.5,0,0.09,0.02,0.10,0,32,3600,140,410,3.0,0.4,0,0,0.02,0.01,0.1,8,0,0.1,4.0,3.8,6,0.2,0,0,0,8.7,350,0.03,1.90,8,5,2,7,0,0,0,0,0,0.1,0.2,0,0,0,0.14,47.0,0,88.4,0,0,0,12.0,0,0,0,0
16,2042,'スポーツドリンク',21,0,0,5.1,0,0,0,0,0,31,26,8,3,0,0,0,0,0,0.12,0,0,0,0.1,0,94.7,0,0,0,0,0,0.1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.8,0,0,0,0,0,0,0,0,0,0
16,2043,'炭酸飲料類 果実色飲料',51,0,0,12.8,0,0,0,0,0,2,1,3,0,0,0,0,0,0,0,0,0,0,0,0,87.2,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
16,2044,'コーラ',46,0.1,0,11.4,0,0,0,0,0,2,0,2,1,0,0,0,0,0,0,0,0,0,0,0,88.5,0,0,12.2,0,0,0,11,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
17,2133
nutritions_df = pd.read_csv("○○.csv")
df = nutritions_df.iloc[:, 3:] #解析に使うデータは4列目以降
# df = nutritions_df.iloc[:, 3:27] #解析に使うデータは4列目以降~27列目まで

栄養素データの大きさにバラツキがあるため、標準化を行います。
栄養素の量(g)は栄養素によって大きさや単位がかなり異なっている(何桁も差があることもある)ため、k-meansの処理をする前に栄養素量データを標準化する処理を行う必要があります。

# 標準化(平均0, 標準偏差1)インスタンス
scaler = preprocessing.StandardScaler()
# 標準化を実行し変数に代入する
clustering_sc = pd.DataFrame(scaler.fit_transform(df), columns=df.columns)

標準化した結果、全ての栄養価の値は-5~5までの範囲に標準化されました。

ここで、k-meansでクラスタリングするには、クラスター数は何個が良いかを計算します。
エルボー法を用いて最適なクラスタリング数を推定します。
***SSE(Sum of Squared errors of prediction)***とは、クラスタ内誤差平方和と呼ばれる量であり、
各クラスタの重心から各点までの距離の総和のようなものです。
エルボー法とは、クラスタの数に応じてSSEを計算してグラフ化し、
その形状から最適と思われるクラスタの数を選択する手法です。
グラフを見ながら、SSEとクラスタ数がともになるべく小さい組み合わせを見つけます。
グラフの変化の仕方が大きく変わる部分が、腕を曲げた際の肘に似ていることから、
エルボー法という名前がついています。

sse_list = []
for i in range(1,30): # 1-30クラスタまで一気に計算            
    km = KMeans(n_clusters=i, init='k-means++', n_init=10, max_iter=300, random_state=0) # k-means++法によりクラスタ中心を選択
    km.fit(clustering_sc) # クラスタリングの計算を実行                        
    sse_list.append(km.inertia_) # km.fitするとkm.inertia_が得られる 
plt.plot(range(1,30), sse_list, marker='o')
plt.xlabel('Number of clusters')
plt.ylabel('SSE')
plt.grid(True)
plt.savefig('elbow-chart.jpg')
plt.show()
plt.close()

エルボー法.PNG

クラスター数が30個以下まででエルボー法で計算しましたが、
この範囲ではSSEは一定値に収束しなかったため、最適なクラスター数はわかりませんでした。
エルボーチャートを書いても適切なクラスター数がわからなそうだったので、
実際に感覚と合うクラスター数を選定してみます。
今回はクラスター数の想定数は15個としており、クラスター数は多すぎず少なすぎない個数が良いので、
一旦は10個または15個として計算を進めていきます。

k-meansを採用してクラスタリングしてみます。
インポートしたデータに対して、K-meansクラスタリングを行います。

# ここでは noc(=15) つのグループに分割 
kmeans = KMeans(n_clusters=noc, init='k-means++', n_init=10, max_iter=300, tol=0.0001, verbose=0, random_state=None, copy_x=True)
kmeans_model = kmeans.fit(clustering_sc)

クラスター番号を表示します。

# 分類先となったラベルを取得する #計算後のラベル情報を抜いたもの
labels = kmeans_model.labels_

# Pandas のデータフレームにクラスタ番号を追加
df['cluster_id'] = kmeans_model.labels_

各クラスターごとに属している食品要素数の分布を表示します。

print(df['cluster_id'].value_counts())

クラスターごとの要素数の偏りが激しく、
20個以上の食品から構成されるクラスターから、食品1個だけから構成されるクラスターまであります。

各クラスターの食品の各栄養価の平均値を求めます。

# 各クラスタの各食品の栄養価の平均値
for i in range(noc):
    print(df[df['cluster_id']==i].mean()) # クラスタ番号 = i

各クラスターの食品の各栄養価の平均値を計算して、積み上げ棒グラフで図示して可視化します。

clusterinfo = pd.DataFrame()
for i in range(noc):
    clusterinfo['cl' + str(i)] = df[df['cluster_id'] == i].mean()
clusterinfo = clusterinfo.drop('cluster_id')
my_plot = clusterinfo.T.plot(kind='bar', stacked=True, title="Mean Value of 15 Clusters")
my_plot.set_xticklabels(my_plot.xaxis.get_majorticklabels(), rotation=0)
plt.legend(bbox_to_anchor=(1.05, 1.0, 0.3, 0.2), loc='upper left', prop={"family":"MS Gothic"})
plt.savefig('bar-chart.jpg')
plt.show()
plt.close()

食品を平面上に図示するために、主成分分析を使用して、栄養素の次元削除を行い、2次元にします。
主成分分析(PCA, Principal Component Analysis)は、主成分(principal component)を見つけることによってデータの次元を低下させます。
データセットの特徴または変数を主成分に基づいて、縮小されたセットに変換することにより、
データの分散を最大化するための最小の変数を得られます。
新しい変数が2つしかない場合、データ内の各サンプルを散布図などの2次元チャートで表すことができます。
まず、60個の異なる変数(栄養素データ)を2次元空間で表現したいので、
PCAを使用することにより、60個の変数を、それらの情報を最もよく捕捉する2つの変数に減らします。
そのために、最初にPCAを実行します。

pca = PCA(n_components=2) # 二次元平面に出力するため、次元数は2を指定 # pca : 成分(軸)を2つに設定
new = pca.fit(clustering_sc)
x_pca = new.transform(clustering_sc) # 新しい2次元平面に落とす # データを2次元に投影した結果
pca_df = pd.DataFrame(x_pca) # Dataframeに変換して列名をつける
pca_df.columns = ['PC1','PC2']
pca_df['cluster_id'] = df['cluster_id'] # 先程計算したクラス分けの結果を足す
pca_df['FoodName'] = pd.DataFrame(data=['こむぎ 食パン','こむぎ うどん ゆで','こむぎ 即席中華めん 油揚げ味付け','こむぎ 中華スタイル即席カップめん 油揚げ 焼きそば','こむぎ マカロニ・スパゲッティ ゆで','こめ 水稲めし 玄米','こめ 水稲めし 精白米 うるち米','こめ もち米製品 もち','そば ゆで','さつまいも 塊根 皮むき 焼き','じゃがいも 塊茎 蒸し','だいず 絹ごし豆腐','だいず 糸引き納豆','キャベツ 結球葉 生','きゅうり 果実 生','たまねぎ類 たまねぎ りん茎 生','トマト 果実 生','ブロッコリー 花序 ゆで','レタス 土耕栽培 結球葉 生','いちご 生','うんしゅうみかん じょうのう 普通 生','パインアップル 生','バナナ 生','メロン 温室メロン 生','りんご 皮むき 生','生しいたけ 菌床栽培 生','ぶなしめじ 生','湯通し塩蔵わかめ 塩抜き','まあじ 皮つき、フライ','べにざけ 焼き','まさば 焼き','あさり 生','しじみ 生','ほたてがい 生','和牛肉 もも 皮下脂肪なし 焼き','乳用肥育牛肉 ヒレ 赤肉 焼き','交雑牛肉 リブロース 脂身つき 焼き','ぶた 大型種肉 ロース 脂身つき 焼き','ぶた 大型種肉 ヒレ 赤肉 とんかつ','ぶた ロースハム','ぶた ウインナーソーセージ','若鶏肉 むね 皮なし 焼き','若鶏肉 もも 皮なし 焼き','若鶏肉 もも 皮なし ゆで','鶏卵 全卵 生','普通牛乳','ヨーグルト 全脂無糖','プロセスチーズ','植物油脂類 オリーブ油','植物油脂類 ごま油','ポテトチップス','ミルクチョコレート','清酒 普通酒','ビール 淡色','ぶどう酒 赤','せん茶 浸出液','スポーツドリンク','炭酸飲料類 果実色飲料','コーラ'])
pca_df.index.names = ['No']

pca_df_s = pca_df.sort_values('cluster_id')

プロットして、散布図を作ります。

# 散布図を描く
ax = pca_df.plot(kind='scatter', x='PC1', y='PC2', figsize=(16,8))
sns.scatterplot(data=pca_df,x="PC1", y="PC2", hue="cluster_id")
plt.legend(bbox_to_anchor=(1.05, 1.0, 0.3, 0.2), loc='upper left') # 凡例の表示
plt.show() # プロット表示(設定の反映)

寄与率を確認します。

print(new.explained_variance_ratio_)

散布図を作ります。クラスター番号によって色分けを変えます。

ax = pca_df.plot(kind='scatter', x='PC1', y='PC2', figsize=(16,8))
for i in df['cluster_id'].unique():
    tmp = pca_df.loc[pca_df['cluster_id'] == i]
    plt.scatter(tmp['PC1'], tmp['PC2'], label='cluster' + str(i))
plt.legend(bbox_to_anchor=(1.05, 1.0, 0.3, 0.2), loc='upper left') # 凡例の表示
plt.show() # プロット表示(設定の反映)

散布図を作ります。こちらでは食品の通し番号もプロットします。

ax = pca_df.plot(kind='scatter', x='PC1', y='PC2', figsize=(16,8))
for i, No in enumerate(pca_df.index):
    ax.annotate(  
        No,
       (pca_df.iloc[i].PC1, pca_df.iloc[i].PC2)
    )
plt.show() # プロット表示(設定の反映)

最後に計算します。

print ('Distortion: %.2f'% km.inertia_)
**レーダーグラフ**を作るコード
# radar : 3つのクラスタの重心
radar = pd.DataFrame(kmeans_model.cluster_centers_)

# 1ずらす
# new_radar : ずらした後の重心データ
new_radar = radar + 1

# データを定義。ラベルと行数,グラフの最大メモリ
labelname = new_radar.columns # ラベルの名前
rownum = len(new_radar) # クラスタの数
max = 2.5 # レーダーチャートの最大メモリ
# 極座標を準備
fig = plt.figure()
ax = fig.add_subplot(111, polar=True)
# 角度設定
angles = np.linspace(0, 2 * np.pi, len(labelname) + 1)
# 北を起点に
ax.set_theta_zero_location("N")
# 時計回りに
ax.set_theta_direction(-1)
# Label名入れ
ax.set_thetagrids(angles[:-1] * 180 / np.pi, labelname) 
# Max入れ
ax.set_rlim(0 ,max)

# データプロット
for i in range(0,rownum):
  values = new_radar.loc[i]

  # データ準備。最初の値を最後に加えることで一周させる
  values = np.concatenate((values, [values[0]])) 

  # データプロット
  ax.plot(angles, values, 'o-')
  ax.fill(angles, values, alpha=0.1)

6.クラスタリング結果と考察

クラスタリングをする上で、以下の条件については現時点では未確定です。

  • 栄養素データは全部で60個用意したが、それらの中でどの栄養素のデータを用いてクラスタリングするか。
  • クラスター数を何個にするか。

上記の2点を色々と変更しながらクラスタリングしていきます。
クラスタリング結果を見て、どの条件の場合に正しく分類できているかを比較することによって、
最適なクラスタリング条件を探していきます。

CASE-1 代表的な4つの栄養素のみを用いてクラスタリングした場合

代表的な4つの栄養素には、三大栄養素であるタンパク質、脂質、炭水化物に加えて、食物繊維も含めた4つを選びました。
これらの栄養素の含有量の情報は商品に記載されていることが比較的多いので、情報を入手しやすいと思います。

clustering_4_radar.PNG

4個の軸:4個の栄養素の含有量(単位:g/100g)

レーダーチャートに図示しました。
各クラスターが4つの栄養素をどれくらいの量を含んでいるかを表しています。
クラスターごとにチャートの大きさ(栄養素の含有量のクラスター内平均値)が大きく異なっています。

clustering_4_bar.PNG

横軸:クラスター番号、縦軸:各栄養素の含有量の合計値(単位:g/100g)

積み上げ棒グラフで図示しました。
各クラスターごとに栄養素の量の内訳がわかります。
炭水化物が多いクラスター、脂質が多いクラスター、炭水化物が多いクラスターなどに分かれています。

clustering_4_scatter.PNG

縦軸、横軸:主成分分析PCAを実行して得られた2個の変数

2次元の散布図にプロットしました。
全ての食品が10個のクラスターに分類されています。
しかし、いくつかのclusterには主栄養成分が異なっている複数の食品が混在してしまっています。
4つ以外のほとんどの栄養素を無視してしまっているために、
分類結果に各食品独自の構成栄養成分などが反映されていません。
その点で分類の正確性に欠けていると言えます。

次に、全ての栄養素の影響を入れるために、60個全ての栄養素データを含めてクラスタリングしてみます。

CASE-2 全ての栄養素データを含めてクラスタリングした場合

クラスター数が10個の場合

cluster番号 食品数 食品
2 36 バナナ、メロン、りんご、しいたけ、ぶなしめじ、わかめ、パインアップル、食パン、せん茶、ぶどう酒、ビール、ホタテ貝、清酒、ヨーグルト、牛乳、コーラ、いちご、みかん、ブロッコリー、うどん、炭酸飲料、スポーツドリンク、マカロニ・スパゲッティ、玄米、うるち米、レタス、そば、もち、じゃがいも、豆腐、キャベツ、きゅうり、玉ねぎ、トマト、さつま芋
6 4 ポテトチップス、カップ麵、即席中華麺
0 1 納豆
5 14 鶏卵、焼き鮭、あじフライ、焼きサバ、ウインナーソーセージ、鶏もも、鶏むね、牛もも、牛ヒレ、牛リブロース、豚ロース、ヒレカツ、ロースハム
9 2 しじみ、あさり
7 1 チーズ
4 1 オリーブ油
8 1 ごま油
3 1 チョコレート

クラスター数が15個の場合

4栄養素の場合よりも多くの栄養素の内訳が一覧で把握できます。

clustering_allnutrition_15cluster_scatter.PNG

cluster番号 食品数 食品 特徴
8 16 ぶなしめじ、しいたけ、食パン、バナナ、マカロニ・スパゲッティ、パインアップル、玄米、いちご、うるち米、玉ねぎ、もち、りんご、じゃがいも、さつま芋、そば 炭水化物、糖質、果物、野菜
1 13 メロン、炭酸飲料、コーラ、スポーツドリンク、あさり、せん茶、ぶどう酒、ビール、豆腐、牛乳、ヨーグルト、うどん、清酒 炭水化物、飲料、糖質、タンパク質
3 2 カップ麵、即席中華麺 炭水化物、脂質
7 1 納豆 タンパク質、大豆
11 7 キャベツ、トマト、ブロッコリー、レタス、みかん、わかめ、きゅうり 野菜、果物、海藻
13 11 焼き鮭、鶏もも、鶏むね、ヒレカツ、豚ロース、牛ヒレ、牛もも、ホタテ貝、焼きサバ、あじフライ、鶏もも タンパク質、肉、魚介類
6 1 しじみ カルシウム、鉄、マンガン
0 3 牛リブロース、ウインナーソーセージ、ロースハム タンパク質、ナトリウム、肉
10 2 チーズ、鶏卵 タンパク質、ナトリウム、カルシウム、鉄
12 1 オリーブ油 脂質、カロリー、飽和脂肪酸、一価不飽和脂肪酸、β0カロテン
9 1 ごま油 脂質、カロリー、多価不飽和脂肪酸
5 1 ポテトチップス 炭水化物、脂質、塩分
4 1 チョコレート 脂質、糖質、炭水化物

表の最右列には、各クラスターごとに共通して含まれる栄養素の特徴を抽出して記載してあります。

4栄養素の場合と比べて、プロットの位置やクラスターの分かれ方が変化しています。
クラスターごとの要素数の偏りが激しく、16個の食品から構成されるクラスターから、食品1個だけから構成されるクラスターまで多岐にわたります。
10クラスターの場合は、構成食品数が36個の大クラスターが出来てしまっていて、
細かく分類できていませんが、
15クラスターにすると、各クラスターにもっとバランス良く食品が分類されています。
同カテゴリーの食品が同クラスターに分類されていることも多いです。
他方で、異なるカテゴリーの食品が同じクラスターに分類されているケースもあります。
しかし、cluster8番およびcluster1番では主栄養素が異なる食品が同じクラスターに入ってしまっているため、課題です。

次に、全ての栄養素を入れてしまうと、あまり関係性の低い栄養素の影響を多少なりとも受けてしまうため、重要度の高い栄養素を20個程度ピックアップして、それらを使って改めてクラスタリングを行いました。

CASE-3 重要な栄養素を20個選んでクラスタリングした場合

クラスター数が10個の場合

cluster番号 食品数 食品
0 26 食パン、ぶなしめじ、しいたけ、りんご、メロン、バナナ、パインアップル、牛乳、ヨーグルト、玉ねぎ、わかめ、ビール、清酒、ぶどう酒、うどん、そば、炭酸飲料、スポーツドリンク、コーラ、マカロニ・スパゲッティ、玄米、うるち米、豆腐、もち、せん茶、じゃがいも
2 5 チーズ、チョコレート、味噌、即席中華麺、カップ麵
4 10 みかん、ホタテ貝、さつま芋、じゃがいも、キャベツ、きゅうり、トマト、ブロッコリー、レタス、いちご
9 2 ポテトチップス、納豆
8 10 鶏卵、鶏もも、鶏むね、ウインナーソーセージ、ロースハム、ヒレカツ、豚ロース、あじフライ、焼きサバ
6 1 焼き鮭
7 2 しじみ、あさり
5 3 牛もも、牛ヒレ、牛リブロース
1 2 オリーブ油、ごま油

クラスター数が15個の場合

clustering_24nutrition_15cluster_bar.PNG

横軸:クラスター番号、縦軸:各栄養素の含有量の合計値(単位:g/100g)

clustering_24nutrition_15cluster_scatter.PNG

cluster番号 食品数 食品 特徴
0 19 食パン、せん茶、玉ねぎ、コーラ、ぶどう酒、ビール、豆腐、りんご、ヨーグルト、清酒、そば、もち、うるち米、玄米、マカロニ・スパゲッティ、スポーツドリンク、炭酸飲料、うどん、牛乳 炭水化物、糖質、カルシウム、他
10 4 ポテトチップス、チョコレート、カップ麵。即席中華麺 高カロリー、脂質、高コレステロール
1 15 わかめ、ぶなしめじ、しいたけ、メロン、パインアップル、みかん、いちご、レタス、トマト、きゅうり、キャベツ、バナナ、じゃがいも、さつま芋 野菜、果物、いも類
7 2 ホタテ貝、納豆 ナトリウム、カリウム、マグネシウム、β0カロテン、葉酸、ビタミンB12
11 1 ブロッコリー β0カロテン、食物繊維
3 9 鶏むね、ウインナーソーセージ、ロースハム、ヒレカツ、鶏もも、焼きサバ、あじフライ、豚ロース、鶏もも タンパク質
5 1 焼き鮭 ビタミンD、タンパク質、カリウム
9 2 しじみ、あさり 貝類
13 3 牛リブロース、牛ヒレ、牛もも 牛肉
12 1 鶏卵 タンパク質、鉄分、葉酸
8 1 チーズ タンパク質、ナトリウム、カルシウム、鉄
4 1 オリーブ油 カロリー、脂質、飽和脂肪酸、一価不飽和脂肪酸、β0カロテン
14 1 ごま油 カロリー、脂質、多価不飽和脂肪酸

10クラスターの場合は、構成食品数が26個の大規模クラスターが発生していますが、
15クラスターの方は、各クラスターにもっと均等に食品が分類できています。
cluster0番だけは炭水化物を中心に多少バラエティーのある食品が混在しているものの、
0番以外のクラスターは総じて主栄養素別に分類できています。
仮説の章で示した食品の分類表と全部が一致している訳ではありませんが、
近い分類結果になっているクラスターもあります。
結果として、全ての栄養素を使ってクラスタリングするよりも、
重要性の低い成分を排除してからクラスリングを行う方が、分類の精度は高まると言って良いでしょう。

このクラスタリング結果は4章の仮説で示した食品の標準的な分類表とある程度一致しているため、
クラスタリング結果が標準的な分類の定義と合っていることを確認できました。
以上のように、k-meansにおいても、食品の標準的な分類に近いクラスタリングができることがわかりました。
栄養学に基づく標準的な分類をk-means法によるクラスタリングにおいても近似できたので、
k-means法は有用性があると言えます。

また、各クラスターから幅広く食品を選択して組み合わせることで、
タンパク質・炭水化物・脂質・ビタミン・ミネラルを始めとする必要な栄養素を
バランス良く摂取できることがわかります。

要素数が多いクラスターを再クラスタリング

ただし、cluster0番およびcluster1番では、
クラスター内要素数が19,15個のように多くなっていて、主栄養素が異なる食品が混在しています。
これらの要素は、クラスター分けにおいて、外れ値ではないその他大勢のような扱いを受けています。
クラスター数を増やしてクラスタリングを行っても、外れ値の要素が入っているクラスターが細分化されるだけであり、その他大勢の集団の細分化はあまり進みません。
この要因は、外れ値の影響が大きく、外れ値に引きずられてしまっているからです。
その代わりに、クラスター内のサンプル数が15~20個と多くなっているcluster0およびcluster1の食品を
抽出して、それらを対象としてもう一度クラスタリングを行ってみます。

clustering_24nutrition_15cluster_re_scatter.PNG

cluster番号 食品数 食品
0 2 食パン、マカロニ・スパゲッティ
1 10 メロン、バナナ、みかん、レタス、トマト、玉ねぎ、キャベツ、きゅうり、じゃがいも、うどん
4 4 そば、もち、うるち米、玄米
8 2 パインアップル、さつま芋
5 1 豆腐
9 1 いちご
2 2 りんご、しいたけ
3 2 ぶなしめじ、牛乳
6 6 せん茶、ビール、清酒、炭酸飲料、スポーツドリンク、ヨーグルト
7 1 ぶどう酒

先程よりも正確に分類できています。
このように、外れ値の要素がいくつかあると、どうしてもそれらに引きずられて、
その他大勢の大集団の細分化が進まないという状態になってしまうため、
大集団に属してる要素を取り出して、それらだけで再度クラスタリングしてみると、
より正確に細分化できるということがわかりました。

7.おわりに

結論

使用する栄養素パラメーターやクラスター数を変化させながらクラスタリングした結果、
下記の知見が得られました。

  • 下記のクラスタリングの条件(クラスター数k、使用する栄養素データ)を最適化することによって、
    現実的に納得感のあるクラスタリング結果を得ることが出来ることがわかりました

  • クラスター数は多すぎても少なすぎても良くないので、
    今回は15個程度(=サンプル数の約25%)がきれいに分類できます

  • クラスタリングに使用するパラメーター(栄養素)は、
    多くても少なくても正確でなくなってしまうので、
    関係性のあるパラメーターを厳選する必要があります

  • クラスタリングの結果、要素数の多いクラスターが発生してしまった場合は、
    そのクラスターの中で再度クラスタリングを実行することにより、
    より細分化されたクラスターを得ることが出来ます

  • 栄養素と食品の分野において、k-means法によって食品の標準的な分類の定義とおおよそ合致したクラスタリングができることがわかりました。
    栄養学に基づく標準的な分類をk-means法によるクラスタリングにおいても近似できたので、k-means法は有用性があるのではないでしょうか

  • クラスタリング結果の各クラスターからバランス良く食品を選択することによって、
    タンパク質・炭水化物・脂質・ビタミン・ミネラルのような必要な栄養素を
    幅広く摂取できるという効果
    があります

以上のような観点から、栄養素データに基づいて食品を分類する際に
k-means法によるクラスタリングは有用性があると言えます

結言

本記事では、栄養素データを使って食品をk-means法によりクラスタリングしました。
クラスタリングを使えば、栄養素について個別に調査することなく、自動で食品を分類することができます。
また、画一的で手間のかかる分類作業をプログラムに任せることができます。
将来的には、ECサイトユーザーに他の類似性の高い食材や一緒に摂取した方が良い食材をレコメンドする
ことに応用できる可能性があります。
このように、食に関わる人や食品産業に携わっている人たちにとって
クラスタリングは食品の分類に最適なツールと言えるのはないでしょうか。

8.APPENDIX

参考

日本食品標準成分表2020年版(八訂)
python
scikit-learn でクラスタ分析 (K-means 法)
scikit-learn 主成分分析を用いてクラスタリングしたデータを可視化する
k-meansの最適なクラスター数を調べる方法
次元削減とクラスタリング
機械学習でマーケティング セグメンテーションを計算してみる【k-means, PCA】

33
25
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
33
25

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?