レンタルウエットスーツのサイズ判定を自動化する

久々の更新となってしまいました。

近頃、現場運営表作りに関するご相談を多く頂きます。

この辺の話題ですね。

VLOOKUP-現場運営表作りの必需品

 

運営表作りの中で、長年の経験を必要とされるのがレンタル器材のサイズ決め。

 

足のサイズからフィンのサイズを決めたり、体重からBCのサイズを決めるぐらいであれば、以下の様に関数でも実現可能です。

IFS-レンタル器材のサイズ判定を自動化

 

変化する量(足のサイズ、体重)が1次元の場合ですね。

 

しかし、ウエットスーツの場合、こうは行きません。

 

同じ170cmでも、60kg無い人もいれば、80kgある人もいます。

変化する量が2つになるだけで、話は一気にややこしくなりますね。

 

ということで、以前僕は、こんなことを考えました。

 

あるデータをいくつかの集団に分類する。

その式はブラックボックスながら、これは今流行のAIで活用される、ディープラーニングがお得意の分野です。

その世界では分類器と呼ばれます。

 

例えば、この分野で例示されるのはなぜか昔から『アヤメ』なのですが、複数のアヤメの品種を分類する、という例がよく示されます。

これは、アヤメの花弁のサイズやがくのサイズなどをデータ化し、それを分類しています。

 

これを応用しまくったのが、顔の検出システムだったりします。

 

話を戻しましょう。

 

実は、以前少しディープラーニングの勉強をした際、手元にある約700人分の身長×体重データを用いて、ウエットのサイズ判定器を作ろうと考えました。

 

結果…

 

ディープラーニング自体に挫折しました…

 

それからしばらくの間、レンタルウエットスーツのサイズ判定問題からは遠ざかっていたのですが、今回ご相談を頂きましたので、再考してみました。

 

仕組み

今回はディープラーニングなんて大それた物は持ちだしません。

ふと、今年の冬に作った物を思い出しました。

採寸をデータ化してみる【採寸補助ツール】

この採寸補助ツールでは

身長×体重×性別と、性別ごとの採寸データの標準値における身長×体重を比較し、誤差の少ない体形の数値を基準値として表示する

という機能を構築しました。

 

この標準値サイズがキッチリと日本人男性の身長×体重をカバーしていれば、これを応用できるのでは?

ということで手元のデータを比較検証。

手元の約700件の身長×体重データのうち、男性で67%、女性では93%ものデータが標準値に収まっていました。

男性に一抹の不安が残りますが、このまま突き進んでみましょう。

 

今回の仕組みはこんな感じです。

  1. 身長×体重×性別から基準値を割り出す
  2. 割り出した基準値の胸囲、腹囲などを抽出(推定胸囲、腹囲)
  3. 推定胸囲、推定腹囲などをレンタルウエットの胸囲、腹囲などと比較
  4. 誤差が最も少ないものを正解とする

 

1、2は構築済み、しかもjavascriptで構築しているので、Googleスプレッドシートで複雑な操作をするためのGoogleAppsScriptとの相性も抜群のはず。

 

ということで、ザクザクっと手を動かすこと2時間?3時間?

ひとまずプロトタイプが完成しました。

 

今回は、テストとしてmobby’sさんのレンタルウエットのデータを用いて判別してみました。

 

結果

mobby’sさんのレンタルウエットの展開は以下の通りです。

男性
サイズ名 身長 体重 上胸囲 胸囲 腹囲 尻囲
M 165 65 94 90.5 80 93
ML 170 70 94 92.5 82 94
L 175 75 98 94.5 84 93
XL 180 80 100 96.5 86 98

 

女性
サイズ名 身長 体重 上胸囲 胸囲 腹囲 尻囲
XS 145 45 80 81 63 88
S 150 50 82 83 66 90
MS 155 55 84 85 68 93
M 160 57 85 86 68 93
L 165 62 87 88 70 95

 

自分の感覚値としては以下の様な感じです。

  • 男性用
    • M
      ~170cm
    • ML
      170cm~175cm
      175cm~178cmで細い人
    • L
      175cm前後でガタイの良い人
      178cm~
    • XL
      180cm前後かつガタイの良い人
  • 女性用
    • XS
      通常は使わない
    • S
      ~155cm
    • MS
      155cm~165cm。万能
    • M
      160cm~でややふっくらした人
      165cm~
    • L
      通常は使わない

 

結果は以下の通り。

 

うーん、思ったより…

というか、グラフの縦軸の取り方が微妙ですね…

 

そして、計算結果としては、身長の影響が色濃く出てしまっている様に感じます。

原因としては

身長、体重、上胸囲、胸囲、腹囲、尻囲を比較しているのですが、よくよく考えると、身長以外は比較的体重に依存しやすい数値なんですよね。

説明変数の多重共線性ってやつですね。

 

ただ、2つのサイズの境界線なんかは比較的良く表現で来ていたので、プロトタイプとしてはまずまずかなと思います。

 

体重だけ単位が違うので体重だけ削ってみる。

それぞれの数値に重みづけをする。

こんな修正を今後、加えてみようと思います。

 

グラフも見やすくした上で、試行錯誤の結果をご報告できればと思います。

 

ちなみに、違うメーカーのレンタルウエットであっても、基準サイズさえ分かればサクッと対応可能です。

※実はGULLバージョンも作ってあったり…

 

実装(参考)

参考&自分の覚書として、実際のコードを載せておきます。

 

function wet_size(sex,tall,weight){
var ss = SpreadsheetApp.getActiveSpreadsheet();
if(sex == '男性'){
var sheet = ss.getSheetByName('MEN');
}else{
var sheet = ss.getSheetByName('WOMEN');
}
var lastcol = sheet.getLastColumn();
var tall_data = sheet.getRange(1, 1 , 1 ,lastcol).getValues();
var weight_data = sheet.getRange(2, 1 , 1 , lastcol).getValues();

var dif = new Array();
for(var i = 0;i<lastcol;i++){
dif.push(Math.abs(tall_data[0][i] - tall)+Math.abs(weight_data[0][i] - weight));
}
var difIndex = dif.indexOf(Math.min.apply(null,dif));
var data = sheet.getRange(9,difIndex+1,5,1).getValues();
var chest = data[0][0];
var bust = data[1][0];
var waist = data[2][0];
var hip = data[4][0];

if(sex == '男性'){
var wetSheet = ss.getSheetByName('WET_M');
var sizecnt = 4;
}else{
var wetSheet = ss.getSheetByName('WET_F');
var sizecnt = 5;
}
var wetdata = wetSheet.getRange(1,2,sizecnt,6).getValues();
var wettall = new Array();
for(var c = 0;c<sizecnt;c++){
wettall.push(wetdata[c][0]);
}
var wetweight = new Array();
for(var c = 0;c<sizecnt;c++){
wetweight.push(wetdata[c][1]);
}
var wetchest = new Array();
for(var c = 0;c<sizecnt;c++){
wetchest.push(wetdata[c][2]);
}
var wetbust = new Array();
for(var c = 0;c<sizecnt;c++){
wetbust.push(wetdata[c][3]);
}
var wetwaist = new Array();
for(var c = 0;c<sizecnt;c++){
wetwaist.push(wetdata[c][4]);
}
var wethip = new Array();
for(var c = 0;c<sizecnt;c++){
wethip.push(wetdata[c][5]);
}

var wetdif = new Array();
for(var j = 0;j<sizecnt;j++){
wetdif.push(Math.abs(wettall[j]-tall)+Math.abs(wetchest[j]-chest)+Math.abs(wetbust[j]-bust)+Math.abs(wetwaist[j]-waist)+Math.abs(wethip[j]-hip)+Math.abs(wetweight[j]-weight));
}
var wetdifIndex = wetdif.indexOf(Math.min.apply(null,wetdif));
var size = wetSheet.getRange(wetdifIndex + 1 , 1).getValue();
return size;
}

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です