ホーム ブログ ページ 11

リモートワークがつらい… 身の回りですぐできる具体策【7選】

0

はじめに最初はリモートワークがつらかった

コロナ禍によって出勤勤務から在宅勤務(リモートワーク)を始めた人が増えているかと思います。
働く場所が変わったことで大なり小なり働き方に影響が出てきますよね。メリット・デメリット両方ありますが、環境の変化に適用できずにつらい思いをしている人もいらっしゃるのではないでしょうか。かく言う私もリモートワークを去年(2020年)の4月から始めて、ちょっと慣れてきた5日目くらいが一番つらかったです。今まで上手くできたことができなくなり、周りに誰もいないのでそれに気づいてくれる人もいませんでした。

工夫することでつらさを軽減

幸いにも私の場合は少しの工夫することで、つらかった気持ちがすぐに普段通りくらいになりました。今回は、どのような工夫をしたら浮上できたか、実体験を元に具体策を挙げていこうと思います。働き方は人それぞれですので、働く人の全員にこの記事が当てはまることはありませんが、参考程度に使えそうなものだけピックアップしていただくといいかと思います。

7つの具体策

  1. いま考えていることをメモや分報にそのまま書く
  2. 終わったタスクは目立つように赤丸⭕️をつける
  3. 照明の明るさを変える
  4. リマインダーでタスクを忘れる
  5. タイマーをかける
  6. 立って作業をしてみる
  7. ラジオ体操をする

ツールを活用する方法

いま考えていることをメモや分報にそのまま書く(おすすめ度:★★★☆☆)

私の場合、仕事をしていると考えることが多く、頭の中で交通渋滞を起こしがちです。作業がうまく進められないことの悩みだったり、急に思い出したタスクだったり、外で雨が降っているかどうか気になったり。そんなときに私がおすすめするのは、そういう日常の思考を断片的な言葉にして書き出すことです。同時に色んなことが気になってどれにも集中できないときに、書き出した内容を眺めて自分の思考を交通整理できます。
少し話が変わりますが、弊社では主なコミュニケーションツールとしてslackを使っており、個人の分報チャンネルを作って発信するのが流行っています(ざっと調べてみると100人分くらいチャンネルがありました)。分報とは今やっている作業や困っていることをひとりごとのようにつぶやいていくことです。自分の分報チャンネルに他の人も入ってもらうことで、Twitterのようにリアルタイムに自分の状態を共有できます。(参考: http://c16e.com/1511101558/

私の分報チャンネル。「(勤怠の)打刻してなかった…!」という嘆きに、チャンネルに参加している人から絵文字でリアクションが来ています。

分報が合う・合わない人はいると思うので、手元のメモアプリなど他の人から見えない方法でもいいかと思いますが、自分が思ったことを率直に書ける場所をもっておくことは精神衛生にも良さそうです。

終わったタスクは目立つように赤丸⭕️をつける(おすすめ度:★★★★☆)

1日の初めにその日のやることリストを書き出す人は多いかもしれません。ひとつ作業を終わらせるたびにリストを取り消し線で消したり、チェックボックスに印をつけたりすることで「この作業は終わった」ということがひと目見てわかるようになります。私の場合は、slackの分報に「済スタンプ」と一緒に投稿しています。スタンプでも赤丸でも何でも良いのですが、ここでのポイントは目立たせることです。

タスクが終わったことが目立つように赤丸の「済」スタンプを多用しています。

一人でずっと作業をしていると終わりがないような気持ちでしんどくなってきてしまいますが、ひとつやり遂げたことを自分自身にアピールすることで達成感を持つことができます。なかなか作業が終わらない時は今の作業をもっと細かく分割して書き出して、小さなゴールをたくさん用意します。細かいことでもひとつ終われば自分を褒めてあげるつもりで赤丸をつけてあげることで「よくやった。終わらない仕事はない」という気持ちになります。

照明の明るさを変える(おすすめ度:★★★☆☆)

画像:Unsplush

会社の照明は作業をするのに一番良い明るさに設定されていますが、リモートワークの作業場となる部屋の照明はそうじゃないこともあるかと思います。自室の照明はリモコンで明るさを変えられるタイプで、業務時間中は一番明るい全灯にして休憩時間や業務後は一番暗い設定にしています。目に入る光の量を変えることで、仕事中の集中モードと休憩中のリラックスモードを自然と切り替えることができます。
ご自宅の照明環境は人それぞれかと思いますので明るさを変えられない場合もあると思います。が、明暗を調整できれば良さそうなので、卓上ライトのオン/オフを切り替えたり、カーテンの開け閉めをしたりすることで調整することもできそうです。
特に休憩中に暗くすることが大切だと感じています。一日中明るいと心が休まらず頭がずっと活動状態になってしまい、ついつい仕事の残りのタスクのことを考えてしまいます。休む時は仕事のことをいったん置いておくことで、気持ちをクールダウンすることができます。

リマインダーでタスクを忘れる(おすすめ度:★★★★☆)

リモートワーク中、他の人からのメッセージや顧客からのメールなどで新たなタスクが増えることもあるかと思います。新しいタスクの優先度によって今やっている作業を続行するか新しいタスクに取り掛かるか変わってきますが、どちらにしろ「今はやらないタスクを覚えておく」という状態が発生します。ただでさえ作業を進めるだけでも精一杯なので、すぐにそのタスクのことは忘れて作業に戻りましょう。とはいえずっと忘れっぱなしは困るので、いつ思い出すことにするかだけ決めてリマインダーを設定することで心置きなく忘れることができます。
リマインダー機能のあるツールはいくつかあると思いますが、私はここでもslackを活用しています。タスクの内容を分報に書き出して、リマインドするタイミングを「20分後・1時間後・3時間後・明日の朝9時」から手軽に選ぶことができます。カスタマイズから指定の日時も選べます。通知が来た後のスヌーズも、いつ再通知するか選ぶことができます。

「後でリマインドする」のメニューからいつ再通知するか選ぶことができます。
時間が経つとこんな風にメッセージが来ます。

「今は目の前のタスクに集中したいから3時間後に考えよう」とか「今日やろうと思っていたけど、今やっているタスクが思ったより重かったから明日に回そう」とか、適切なタイミングで思い出すことができるので安心して忘れることができます。頭の作業領域を「これやらなきゃ」「あれやらなきゃ」で埋めてしまわないことが狙いです。

タイマーをかける(おすすめ度:★★★★★)

スマホのタイマー機能やキッチンタイマーなどを使って15分ごとにアラームを鳴らします。効果は「我に帰る時間を強制的に作れる」です。(15分は目安なのでお好みで!)ひとりで黙々と作業していると「自分」と「今やっている作業」がすべてになってしまい、仕事の全体像が見えなくなりがちです。定期的に自分の現在地を確認することで、次にやることへの見通しを立てたり、なかなか進まないタスクを一旦切り上げたりすることができます。私の場合は、このタイミングで一息ついて水を一口飲んでいます。さらに時間の区切り(始業・昼休憩・終業)でもアラームをつけることで、オンとオフの切り替えの手助けになります。タイマーさえあればすぐに始められるところもおすすめポイントです。

iPhoneのアラーム機能を活用して、学校のチャイムのように定期的に音を鳴らします。自宅なので周囲の目を気にする必要なし!

体を動かす方法

立って作業をしてみる(おすすめ度:★★★☆☆)

画像:Unsplush

立って働いているオフィスワーカーの人がいると聞いて実際にやってみました。昇降式の机があるとPCも一緒にあげることができていいのですが、そんなものは無いので机の上に台や椅子を置いて高い位置にPCを配置しました。気分をガラッと変えたいと思った時に突発的にやると良かったです。物理的に視線が変わることで強制的に気分が変わります。
私の場合はプラスアルファとして、好きなBGMを鳴らしながら踊りながら仕事をしています。テンションが上がるので単純作業などに向いています。ずっと動いているのも疲れるので30分程度が限界です。

ラジオ体操をする(おすすめ度:★★★★☆)

ラジオ体操は3分程度で終わるので、ちょっと体を動かしたいときに最適です。業務開始前に体を動かしておくと、頭もだんだん働き始めるような気がしています。
iPhoneをお持ちの方でさらにおすすめなのが「オートメーション」という機能で毎朝決まった時間に自動でラジオ体操を流れるようにすることです。時間になったら通知が届き、ワンタップだけでラジオ体操の曲が流れ始めるので「しょうがないやるか〜」と自然に動き始めることができます。

毎朝9時に一連の処理をするようにオートメーションを設定しています。ヘルスケアサンプルのアプリケーションで体温を記録させてから、ラジオ体操が流れるURLが開きます。

おわりに:大切な具体策をもうひとつ

いかがでしたでしょうか。長々と書いてまいりましたが、ここまで読んでいただきありがとうございます。今回取り上げたリモートワーク以外でも、仕事上のモヤモヤは色んな工夫で乗り切れると嬉しいですね。
ただ、正直リモートワークがつらい要因は個人の工夫だけでは解決できないことも多いので厄介です。コミュニケーションがうまくいかないことのモヤモヤや自宅の環境が仕事場として整っていないこと、などなど。工夫しても上手くいかなければ「他の人に相談することが仕事だ」と視点を切り替えてみてもいいかもしれません。自分だけでなんとかしようとせずチームで乗り切ることも「仕事を遂行する」という目標において大切になってきます。また、仕事の進捗に関係なくても、つらい気持ちを誰かに打ち明けると何か道が開けるかもしれません。誰かに相談することも具体策のひとつです。
コロナ禍での2回目の緊急事態宣言で、一度は減ったリモートワークが復活して憂鬱な方もいらっしゃるかもしれません。休むときはしっかり休んでご自愛してくださいね。お互い支え合って工夫で生き抜いていきましょう!

Webデザイナー1年生におすすめするデザインの練習方法

0

こんにちは。デジタルビジネス部のWebデザイナーAです。

今回は私がWebデザイナー1年生の頃にやっていたデザインの練習方法について紹介します。
皆さんがバナーやサイトのメインビジュアル、Webサイトのデザインを制作するときに少しでも役に立てれば幸いです。

私が実践していたのは以下の4つです。

  1. デザインを見て学ぶ
  2. Webサイト以外のデザインから学ぶ
  3. デザインを真似して学ぶ
  4. 学んだことを応用してオリジナルのバナーやサイトのデザインを作ってみる

1. デザインを見て学ぶ

最初はとにかくいろんなサイトを見ることを意識してやっていました。
あとはグロナビやボタン、アイコンなどのパーツ単位で気になったデザインをエクセルにまとめて、デザイン制作で悩んだときに見直せるような資料も作っていました。

流行りや最近のデザインの傾向を知ることにも役に立ちますし、何より制作意欲への刺激になります。
例として私が普段見ている主なサイトも掲載しておきます。

Webデザインのまとめサイトの例

WebDesign
国内サイトだけでなく海外サイトまで幅広く網羅。
デザインの参考になるクオリティーの高いサイトが約2800件掲載され、カテゴリー検索だけでなく、タグ検索、レイアウトタイプやメインカラーでの検索も可能。

SANKOU!
国内サイトのみをピックアップ。
カテゴリ検索の内容が具体的。(例:シズル感・訴求力がある写真・動画・映像)
フィルター検索で細かい絞り込みも可能。

81-web.com
国内サイトのみをピックアップ。
サムネイルにhoverするとサイトに該当するカテゴリ・カラー・タグを見ることができる。
サイトのお気に入り登録機能が便利。(Webサイトのボックス右下にある+ボタンで登録して、メニューのFavoriteから登録したサイトを閲覧できる)

MUUUUU.ORG
クオリティが高く縦に長いサイトがピックアップされているので、TOPに情報や写真を多く掲載するサイト制作時に参考になる。

bookma!
サムネイルにPCとスマホの表示画面が一緒に掲載されているため、レスポンシブデザインをする時の画面の見え方のイメージを膨らませやすい。
1サイト1カラム構成になっているので、色んなサイトのファーストビューをじっくりみたい人におすすめ。

1GUU
国問わずとにかく色んなサイトをみたい人向け。
国内と海外サイトが掲載。アニメーションのあるサイトはサムネイルの時点で動きの確認ができる。海外サイトの国別または7大州ごとに絞り込み検索が可能。

Pinterest
Webサイトに限らず色んなデザインを集めたい人向け。
ユーザー登録(無料)の必要あり。
該当する画像をボード(ブックマークフォルダ)にピン留め(ブックマーク)するサイト。
ボードには任意の名前をつけられ、他のユーザーのボードもフォローして閲覧することができる。

2. Webサイト以外のデザインから学ぶ

雑誌や広告のレイアウトもWebサイトのメインビジュアルやコンテンツのタイトルデザインを作る上で役に立ちました。

雑誌や広告はWebと同じく限られた空間に情報をわかりやすく見せ、かつ掲載されている内容にあったデザインがされているので、普段からジャンル問わずチラ見しておくと何かの役に立つ時が来ます。
実際、私もファッション紙やデザイン情報誌などから発想を得た経験があります。

見ておくと良いポイントとしては、文字間や文字の配置とデザイン、使われている色、イラストやデザインの配置、ロゴの配置などです。
あとは細かい装飾の部分で、アクセントになっている遊びの部分なども意識して見ていました。
(手書きのイラストや文字、筆記体の文字、アナログ素材(紙など)で柔らかさを出している背景、背景色から少しずらして配置されている写真など)

3. デザインを真似して学ぶ

気になったサイトやレイアウトがまとまって見やすいバナーなどをスクリーンショットして、Photoshopで上からデザインをなぞっていました。

実際に自分で真似して作ることで、文字の間隔やサイズ、フォントの種類はどんな系統のものが使われているのか、どんな加工や配色になっているか、写真やイラストなどの配置がどんな風に作られているのかがわかります。

実際に手を動かすことで、見るだけでは得られない数値単位での情報やデザインの技術が自分の中に自分の中にストックされていきます。

4. 学んだことを応用してオリジナルのバナーやサイトのデザインを作ってみる

今までの3つを踏まえた上で、架空のクライアントを立ててオリジナルのデザインを作ると、さらに自分の力になります。

架空のクライアントが思いつかない場合は、自分の趣味や好きなものを題材にしてみるのも良いです。
Webサイトのデザインを作った場合は、コーディングまでやってみるとさらに力が尽きます!

最後に

以上、4点を業務の隙間時間に少しずつ積み重ねてやっていくと、実際の業務で役に立つことがあるでしょう。

是非、実践してみてください。

「育児も手続きも段取りが大事!」男性の育児休業について

0

政治家が男性育児休業を取得したことが話題になるなど男性育休に対する社会の関心は高まりつつあり、取得率も上昇しています。でもまだまだ少ないです。先日アピリッツの男性社員が育児休業を取得しました。アピスピにも何度か登場してくれている3DCGデザイナーの立原さんです。手続きや育休中の様子、育休明けの仕事について教えてもらいました。(2020年 12月取材)

プロジェクトメンバーの後押しで育休取得

ーー 「育児休業を取ろう!」と決めたキッカケを教えてください

人事企画部の方との世間話で妻の妊娠を話したことが始まりです。「おめでとう! 育休取れるよ!」と言われて「いいんだ!?」と思いました。相談しようかなとは少し考えていたのですが、先に提案してもらえました。

家族も「あ、取れるの? よかった!」といった反応で、喜んでくれました。

ーー 育休取得の手続きや相談はスムーズに進みましたか?

はい。手続き面は人事企画部の川口さんと大越さんが「育児休業給付金」や「健康保険」を調べてくださり、フォーマットも作ってくださったので、すごく助かりました。自分でIT健保に相談して進めようと思っていたので……。

仕事面は、プロジェクトリーダーの和田さんやメンバーが「ぜひ取って!」と快く応じてくれたのでありがたかったですね。ふだんから仕事を1人で完結させないでいろんな人に見てもらっていたので、安心して送り出してくれたのかな、とも思います。

日頃からのコミュニケーションの大切さをあらためて感じました。

また、あらかじめ後輩に仕事を共有して教えてきました。みんなが成長してくれたことも今回の育休取得の後押しになったと思います。

ーー 育休に入るまではどのような準備をしましたか?

まず、仕事の引き継ぎです。自分の作業を早めに片づけて準備しました。同時に妊娠中の妻のケアもあったので肉体的にも精神的にもエネルギーがいりました。

しかも出産予定日よりも早めに産まれたんです。手続きや引き継ぎを一ヶ月以上前から進めていたので間に合いましたが、ちょっと焦りました。ですから、これから育休を検討する方は早め早めの準備をおすすめします! 赤ちゃんには赤ちゃんのスケジュールがあるので、こちらの想定と全然ちがう進行だって十分ありえますから!

「大変なこともいっぱいあるけれど、愛しさがまさりますね」と立原さん

ーー 育児休業は何日取得しましたか?

21日間です。和田さんからは「一ヶ月でも二ヶ月でもいいよ!」と言っていただけたのですが、ちょうどプロジェクトのリリースが近づいていたので、もろもろ考慮して今回の育休は21日間に決めました。

ーー 育休中はどんなことをしましたか?

料理・掃除・夜中の育児は自分担当としました。夜中は妻に寝てもらいたかったので。洗濯は妻にお願いしました。その他の家事は「できる人がやる」と臨機応変に分担しました。妻の母親と同居しているので、たびたび手助けしてもらえています。

タイムテーブルは次のような感じです。

時間やること
0時ミルク
趣味の時間
睡眠
4時ミルク
睡眠
7時ミルク
朝食
10時ミルク
昼食の支度
昼食
13時ミルク
グラフィックの勉強
16時沐浴
ミルク
グラフィックの勉強
夕飯の支度
19時ミルク
夕飯
風呂
21時ミルク
寝る準備
寝室でのミルクや空調・加湿器の準備
24時ミルク
新生児のお世話の一部

ーー ミルク、3時間おきなんですね。赤ちゃんって一日八食……?

はい! 産まれてすぐのころは赤ちゃんの体もお腹も小さいので、少し飲むだけですぐお腹いっぱいになるんです。育休に入る前は「空き時間にCGの勉強をするぞ」と思っていたのですが、フタを開けてみたらそんな時間は全然なかったです(笑)息子はあまり寝ないで起きていることが多い子なので、随時おむつを交換したり、あやしたり……。できるだけ妻とも会話をたくさんするようにしました。

復帰後の生活リズムを予行演習

ーー 復帰に向けてどんなことを意識しましたか?

まずは家庭内の体制づくりです。私が復帰したあとの育児の分担をどうするか話し合って、その生活リズムをあらかじめ作っておきました。家族みんなが健康でいてほしいので、いきなり日常が変わって体調が崩れないように気をつけました。

ーー 生活リズムって大事ですよね。育休中、仕事は気になりましたか?

仕事、恋しかったですよ! アピリッツでのお仕事はどれも好きですし、私が育休中に作業を負担してくれたプロジェクトメンバーへの感謝と申し訳なさがあったので。それに、私自身、周囲から取り残されていく焦りもありました。プロジェクトの進行状況もとても気になりましたし。

なので、一年以上育休を取る方々の大変さや焦りに少し共感できるようになったと思います。

ーー 復帰後、仕事のすすめ方は変わりましたか?

なるべく時間内に仕事を終わらせて帰るようにしています。育休に入る前は引き継ぎ作業などで残業しがちでしたが。育休があけたあとも夜中の育児は自分が続けています。

ーー え! 眠れていますか?

まとまった睡眠はとれないので、眠いです! でも、ちょっとずつ泣く回数やミルクの回数も減ってきて、子どもの成長を毎日感じています。毎日うれしさがあります。2020年のクリスマスは、初めて家族と子どもと過ごしました。息子はまだわからないはずですが、大きくなったら「最初のクリスマスはこんなだったんだよ」って見てもらいたくて、記念にムービーや写真を撮りました。

ーー あらためて育休を取得していかがでしたか?

取得して本当によかったと思います。出産って本当に大変なことでした。お母さんは身も心もボロボロになります。パートナーが一番つらくて大変なときに側にいることができてよかったです。あと、段取りの大切さを痛感しています。育休の準備も、夜中のミルク作りの準備も、どちらも段取りが肝心ですよ!

ーー ありがとうございました!

関連記事:立原さんのお仕事に関する記事はこちらです『次元が一つ増えることで表現は倍増する」今需要が高い3Dデザイナーと、3DCGの制作工程を紹介!

売れるゲームとは?面白いゲームとは?企画の育成プロセスをまとめてみた

0
ゲームアイディア
売れるゲームとは?面白いゲームとは?

コンテンツデザイン部 A(仮)です。

アナタの考える売れるゲーム・面白いゲームはなんでしょうか?

本記事はその『アイディア』を育成させるプロセスをまとめます。

※個人の記事執筆であり、会社としての見解ではございません。


0.その前に…なぜそのゲームか?

売れるゲームとは?

遊んだら「面白い」ゲームは売れない

2020年現在、ゲーム市場は数多くのゲームであふれ、且つ多くが基本無料(Free-to-play)のゲームです。

アナタは今年、いくつのゲームを知り、いくつのゲームを触り、そしていくつのゲームを遊んだでしょうか?

それから言えることは「パッと見よくわからない(興味をそそられない)から無料であってもやらない」「少しだけ触って辞めた」が大半ではないでしょうか?

1時間プレイして面白さがわかるゲームを売ることはとても大変です。それはCAC・CPI(顧客獲得単価)にも直結します。

パッと見で面白さへの体験イメージがつくクリエイティブ(タッチポイント)は最低条件であり、さらにモバイル環境のユーザーだと仮定すると数分で「面白い」を味合わせることができることも必要です。

面白いゲームとは?

ゲーム業界内ではよく言われることではありますが、

第一欲求を動かされ、それを満たせるかどうか。

カタルシスがあるかどうか。

https://www.famitsu.com/serial/chasergame/202003/09194054.html
https://gamebiz.jp/?p=142333

しかし、そもそも「面白い」とは不確実な価値でありKPIの視点では推計が行いづらいです。

ですが、売れた面白かったゲームは数字で説明が必ずつくと思っています。(実際に数値化しているかどうかは別です)

よって売れる面白いゲームへの予測精度は高められると考えており、本記事ではアナタの新しいアイディアに対してただ「それ面白いの?」ではなく、フレームワーク的に数値化&検証精度をあげていきます。


1.アイディア育成のプロセス

1.1ロードマップを大枠で書く

・顧客の欲求のステージと価値のレベルはリンクしていますか?

ロードマップ

全体構造をまとめましょう。そのアイディアがもたらす、欲求の最終ステージから逆算して考えていきましょう。価値は数字などは使わず大枠イメージでこの段階では問題ありません。

1.2KPIツリーを作成する

浮かんでいるシステムイメージやジャンルを元に当該システムを採用している類似競合から各KPIを調査します。

類似競合のインストール数・ARPDAU(日別平均ユーザー数)・RR(継続率)・PUR(課金率)などから、推計しましょう。(マーケディングツールを用いると効率的です)

また後記の1.3,1.4を行っている段階で、獲得コストや開発コスト等のコスト面も逆算して追加推計していきます。

1.3市場規模を調べよう

TAM,SAM,SOMのを複数の角度で推定できますか?

・SOMとファイナンシャルズ(KPI)の規模感はあっていますか?

市場規模

初めにトップダウン分析を行います。次に1.2のKPIを含めボトムアップでも分析を行います。両方の視点から行うことにより、“ズレ”がないか”偏り”がないかを見直すことができます。

トップダウン例:[TAM]2019年世界モバイルゲーム市場は7兆1840億円 [SAM]××アクションカテゴリだと○兆○○○億円 [SOM]そのうち□□%シェア獲得で○○○億円

ボトムアップ例:1.2のKPIから、顧客数×顧客平均単価でSAMへの推定。その顧客のサービスに対するニーズをどのようにして市場を作り出し売っていくか、顧客のニーズを定量調査しまとめます。IPが決まっている場合は、ファンの想定母集団と想定購買力からも推計することができます。

1.4 UIフロー + モチベーション + ロイヤリティ

1.1~1.3までを深掘りしていく

UIフロー + モチベーション + ロイヤリティループ
※本画像は簡易的な製作イメージです

画面遷移項目(≒UIフロー)に、『モチベーション(気持ち)』+『ロイヤリティ(お金)』を入れ込みましょう。

本図を作る際、すべてを初めから作ろうとせず徐々にブラッシュアップましょう。また1.2&1.3より、各画面遷移別で『モチベーション(気持ち)』『ロイヤリティ(お金)』の”予測数字”をできるだけ細かく記載できるようにしましょう。ユーザーの成熟度に応じて記載するとより精度が上がります。

モチベーションやロイヤリティがループしているかを必ず見直しましょう。

※売り切りモデルは『ロイヤリティ』を省きます。


2.まとめ

本記事は読むだけではなく、実際に書き落としこむことが大切です。

1.1~1.4までを繰り返し書き終えているころには、アナタの考える売れる・面白いゲームは、価値の数値化や仮説検証までができているでしょう

今回の記事執筆の背景として、現状改めて可視化・蓄積していくことがこれからのゲームクリエイターはより一層必要なことなのではないかと感じているからです。

参考文献:ダイアモンド社『世界標準の経営理論』,㈱グロースハックスタジオ『THRUSTER』,㈱アンド『ビジネスフレーム図鑑』

▼「具体例や実際の値はないのか。なんだ。」と思った方以下よりお問い合わせください。また異業種であってもゲーム要素(ゲーミフィケーション)でのソリューション提供を弊社では行っております。

▼またここまで読んでいただいた、売れるゲーム・面白いゲームを創りたいと真剣に考える方、そういった組織・環境に興味がある方、ぜひ私と一緒にお仕事をしませんか?

DAU30万を想定したソーシャルゲームの負荷試験の為の事前準備

0

 こんにちは。CD部の金井と申します。今回は大規模な負荷試験の準備に関する事を書いていこうと思います。

そもそも負荷試験って何の為にやるの?

 リリース当初のゲームに良くありがちな事ですが。
 ユーザーアクセスの集中によってサーバーが落ちてしまい、そのまま長期メンテナンスに入った、と言うような事柄は目にした事があると思います。
 他にも新イベントが実装された時や期間限定のガチャが開催された時にユーザーが数多に戻ってきて、レスポンスが重くなったり。
 端的に言うならば、負荷試験はそのようなサーバー不具合を防ぐ為に行うものです。
 もう少し具体的に書くならば、

 リリース前に行う負荷試験としては、

 ・初日に起こり得るであろうリセマラに対して
 ・実装したイベントに対して
 ・また全てのAPIに対して


  ・レスポンスは許容出来る時間内に返せるか?
  ・用意したAPIサーバー、データベースサーバー、キャッシュサーバー、リアルタイムサーバー等々は想定したユーザー数のプレイに耐え得るか?
  ・想定以上のユーザー数がプレイに興じた場合どのような影響が発生するか? サーバー自体は落ちずに、レスポンスが重くなる程度の影響に留められるか?
  ・万一どこかのサーバーが落ちた場合、障害によって如何なる影響が発生するか? ユーザー不利益は発生しないか? 自動復旧の仕組みは整っているか?


 という事を確認する必要があります。
 また、リリース後にも新機能の実装時などには負荷試験を行うべきですが、その時は新しく実装された、影響された範囲だけを追加で調査すれば基本的に大丈夫ですので、そこまで大変ではないです。

新機能のリリース1週間前に負荷試験にて巨大なボトルネックが発見されて、やり直しになったテストフェーズに泣くQAチーム

負荷試験の為に何を準備すれば良いの?

 端的には以下の3つです。

  1. どのような負荷試験を行うか、調査する事を明確に定めた負荷試験計画書
  2. 実際にサーバーに対して負荷を掛ける、リクエストを投げる為のシナリオプログラム
  3. そして、負荷試験の為の環境

 一つ一つ見てきましょう。

スケジュールが緊迫しているというのに、こんな時に限って会議の為の部屋が全て埋まっていてミーティングが出来ないエンジニア

1. 負荷試験計画書

 これが無いと負荷試験は始まりません。
 当たり前な事ですが、明確な目標やゴールが見えないままに負荷試験を行ったところで、大した成果物は発生しません。
 その為に、上記で書いたような事を明確な数値、試験内容として定める必要があります。
 例えば、

  • 想定DAU(Daily Active User……1日に遊ぶユーザー数)は30万人とする。
  • サーバーのCPU、メモリはユーザーが最もプレイする時間帯でもそれぞれX%, Y%までに留まるようにする。
  • 負荷試験中にユーザーデータを保存しているデータベースの1台を落とす。N分以内に自動復旧し、正常に遊べるようになる事を確認する。

 等々とても割愛していますが、様々な状況を想定して、それらに対する目標値を定めなければいけません。

 さて、ここでタイトルにもあるようにDAU30万を想定するならば、RPS(Request Per Second……秒間に飛んで来るリクエストの数)はどれ程を想定すれば良いのかを算出してみましょう。

 計算式は以下です。

 RPS = DAU × 最大でどれだけの割合の人数が同時に遊ぶか × リクエストは何秒に1回叩かれるか

 まずDAUは、上の人……要するに製作しているゲームのターゲット層、想定プレイ人数を定めているお偉い人から聞き出しましょう。ここでは表題の通り、30万とします。
 次に最大でどれだけの人数が同時に遊ぶかですが、これに関しては自分の経験にはなりますが、DAUの10%~30%で定めた事がありました。ここでは多めに30%としておきましょうか。
 そして最後のリクエストは何秒に1回叩かれるかに関しては、これは実際に遊んでみて確かめてみましょう。ここでは10秒に1回サーバーにリクエストが飛ぶ、と仮定しましょう。
 すると、上の式は以下となります。

 RPS = 300000 × 0.3 × 0.1
 RPS = 9000

 要するに、秒間に9000のリクエストが捌ければ良い訳ですね! 大変だぁ。

 また、負荷試験というのは最初からこんな9000RPSなどといったデカい値を数多のサーバーに対してぶん投げるのではなく、サーバー単体での性能から測っていくものですが、この単体の性能が貧弱だと想定人数を捌く為に必要なサーバー台数も必然的に爆上がりします。

 例:
 1サーバー辺りのスレッドが20あるとして、リクエストが平均200msecだった場合、そのサーバー1台が秒間で捌けるリクエスト数は 20 * 1000/200 = 100となる。
 9000RPS…秒間リクエスト9000を捌く為に必要なサーバーの台数は9000/100 = 90台。
 また、スレッド数20を実現出来るサーバーは、AWSだとオンデマンドで大体1時間に1\$の料金が発生するサーバーになる為、この性能をオートスケーリングとか何もなしでオンデマンドで常に立てておくと、一月辺りの料金は、

  • 1日に1台で掛かる料金が24\$
  • それが90台で30日の2700倍で64800\$

 日本円に換算して大体674万円!
 ひゃっほう!
 因みに言うとこれ、APIサーバーだけで掛かる金額なので、データベースサーバーとかキャッシュサーバーとか鑑みるともっと増えます。

 何が言いたいかと言うと、サーバーコストを削減する為にも綺麗で速いコードと言うのは常日頃から心がけておくべきですね。リファクタリングによって月100万単位でコストを削る事も可能になるかもしれませんよ。
 まあ、上記の例だとリファクタリングより、スポットインスタンスやらオートスケーリングやらを活用した方が安くなると思いますけど。

現状の性能から試算されたサーバーコストに泣くディレクター

2. シナリオプログラム

 準備が一番大変なのは、計画書よりも環境よりも、こいつです。
 結局、疑似的にクライアントを作るようなものですからね。
 基本、全てのAPIに対して投げられるようにシナリオプログラムは作ります。そして、データベースのインデックスが効いているか等を確かめる為にも、ある程度ランダム性も持たせなければいけません。
 場合によっては、暫く待たなければ結果が出来ない仕様のデータを早送りして即座に結果を受け取れるようにさせる、フレンドからの干渉によるデータを疑似的に作成する、等といった負荷試験専用のデバッグAPIなどをSV側に作ったりする必要も出てきます。
 これに関しては開発中からコツコツ作っておくのが吉だと思います。負荷試験をすると決めてから作るとした場合、余裕で二週間とかは掛かると思います。

 また、その負荷を掛ける為のツールは幾つかありますが、自分はJMeterLocustに関して使用経験があります。

 JMeterはシナリオに書き辛い部分があったり、実際に負荷試験本番で使う場合はCUIから結構複雑なコマンドを投げたりしなければいけませんが、出力結果を纏めたり比較したりするツールがGUIに内包されており、そこは便利です。

 Locustはシナリオは書き易く、実際に負荷試験本番で使う場合もGUIを使って簡単に操作出来ますが、結果はCSV等に出力出来るだけで、そのCSVからまた色々比較検討する際にはExcelなどを使わなければいけません。

 総合的に言えばLocustの方が良い印象です。
 負荷試験はプロジェクトで一回切りのものでもありませんし、手間を掛ける煩雑さに関しても

 負荷試験を実行する > 負荷試験の結果を纏める

 な事には間違いありませんから。

負荷試験に必要な100近いAPIのシナリオを書くのを1週間で命じられたエンジニア

3. 負荷試験の為の環境

 リリース後にも負荷試験を行う必要性が出てくるであろう事も考慮すると、リリース前の本番環境を負荷試験環境にしたりするのはあんまりお勧めしません。
 ただ、基本的に使う必要の無い負荷試験環境を立てっぱなしにしていては、勿論無駄なお金が掛かります。
 また負荷試験の実行フェーズでも、本番環境と同等の環境にしていた場合、負荷試験をしていない時間には出来るだけサーバーは落としておくべきです。
 上記の例だと、その本番環境と同等にしていた場合には、19時に帰宅して翌日の10時に出社するだけでも1350$掛かりますからね! もし金曜に立ち上げっぱなしにしてしまった場合、月曜に気付いた時にはお給料以上のお金が吹っ飛んでいますね! とっても怖いですね!
 そんな事で、負荷試験環境はスクラップ&ビルドが簡単な状態にしておく事が望ましいです。……とても大変ですけど。

 また、本番想定の為、DBの負荷を正常に測る為に想定ユーザー分のダミーデータをDBに突っ込んでおく必要もあります。
 これに関しては、最初にリセマラを想定した負荷試験をすれば行う必要も無くなる事もありますが、スクリプト等を別途組んでおけば楽になるでしょう。

環境の立ち上げが一向に上手くいかないエンジニア

負荷試験スタート

 さて。
 ここまで整えて、やっと負荷試験はスタートを迎える事が出来ます。
 上記の通り、スタートを迎える為に準備する事柄は数多にありますので、負荷試験フェーズに入ってからの一からの準備ではもう手遅れ、残業塗れになる事は想像に難くありません。
 そんな事にならない為にも、開発フェーズから負荷試験の事は考えておく事をお勧めします。

*****

「よし! 単体サーバーで150RPSまで捌けるようにコードの改善も出来たぞ! 性能が1.5倍! コストは2/3! ダミーデータもたっぷり入れたし、これからサーバー台数を一気に増やして本番想定の負荷試験だ!」
「すまん、リリース前だが仕様変更だ」
「えっ、ちょっと、この仕様テーブル定義かなり変わるじゃん、土日掛けて突っ込んだ膨大なダミーデータ無駄じゃん」
「すまんが頼むね」
「…………」
 頑張りましょう。

駄々をこねるエンジニア

え、まだ健康診断うけてないの?って言われない方法

0

はじめに

「健康診断受けてね!!」
「まだ予約してないの!!?」

年末になると健康診断担当から沢山届く通知……
アピリッツ年末の恒例といっても過言ではないはず……
(恒例化したくない;;)

正直、健康診断メンドクサイと思っている人、いると思います。

と、いうことで
どうして健康診断ってうけなきゃいけないの?
どんなメリットがあるの???
について、健康診断担当者がわかりやすくお伝えしていきたいと思います!

これを読めば、来年からは「え、まだ健康診断うけてないの?」って言われなくなるはず…です!

どうして健康診断をうけなきゃいけないの?

★そもそも法律で決められている!!

健康診断の受診は、労働安全衛生法第66条で定められた義務です。

出典:労働安全衛生法 第66条

企業の義務
「事業者は、労働者に対し、厚生労働省令で定めるところにより、医師による健康診断(中略)を行わなければならない。」

労働者の義務
労働者は(中略)事業者が行なう健康診断を受けなければならない。


健康診断を行うことは「企業(アピリッツ)と労働者(アピリッツで働く人)それぞれの義務」で、受診させない・受診しないことは法律違反になってしまうのです…!なので健康診断担当者は「健康診断、受けてね!!」と連絡を沢山しているワケなんですね。ふむふむ。

毎年健康診断を受けていれば、カラダの経年変化に気づけるし、病気を早期に発見することもできるかもしれません。(事実、社員の中には、健康診断のおかげで初期で病気を発見できた方も……!)

しかもアピリッツでは会社で初回の健康診断費用を負担してくれる!

自己負担無しで自分について知れる……しかも婦人科検診オプションも1個自己負担なしで付けられる……だと? え、すごくない?|д゚)

ふーん、なるほど。
健康診断はやっぱり受けなきゃなのね~~

その通りです、アピ子さん。だんだん健康診断受けたくなってきましたか?(笑) ここでさらにすごいポイント!

ここがすごいよ!アピリッツの健康診断!

★MY HEALTH WEBで、健診結果がまとめて見れるらしい

MY HEALTH WEBとは、アピリッツが加入している関東ITソフトウェア健康保険組合の個人向け健康ポータルサイトで、アピリッツで健康保険に加入している人であれば皆さん使えるものです。ポイントでアイテム交換できたり、医療費通知の閲覧ができたり色々便利なサイトのようですが、健診結果の閲覧もできる!

提携している病院であれば、どの健診期間で受診したものでも一元管理できるとのこと!

これで「結果をまとめて見れるから、いつもの病院で予約したいけど予約いっぱいで健康診断受けられません………」なんて問題もクリアですね!! ※MY HEALTH WEBの詳細はこちら

★会社内で健康診断受けられる

「わざわざ病院に行くのめんどくさいな」という声にお答えして、年に1度病院を会社に呼んで会社で健康診断を受けられるようにしています!(2020年度はコロナ感染防止のため中止)

★業務扱いになる

実は、健康診断の時間って労働基準法によると労働時間ではないのです! でも、アピリッツでは平日に受けた健康診断の時間は業務扱い(労働時間としてカウント)となっています。業務扱いになりますので、皆さんきちんと健康診断受けてくださいね★

健康診断の重要性はわかりましたよ、でも早めに受けなくてもいいのでは?

いやいや、ちょっとまってくださいなアピ子さん。

早く受ける(予約)すると何がいい??

★余裕を持って受けられる

12月までとかに受けとけばいいや~と思っている人はご注意を! 年末は駆け込み予約が多いです。「ギリギリに受けようと思ったら、行きたいところが予約いっぱい!家から遠い所で受けなきゃ;;」みたいにならないように余裕をもって予約しましょう! 健康診断担当から、せかされることもなくなります(笑)

★健康診断担当者、嬉しい^^

実は健康診断担当者が、健康診断の受診状況を労働基準監督署に提出しています! 早めに予約・受診してもらえると、余裕をもって受診状況を報告できるので担当者、嬉しい。(喜びかみしめる) 年末に今年度もちゃんと法律を守れるか、ドキドキする必要もありませんね^^

ほうほう、ということは
健康診断の案内が来た時点で先に予約しちゃえば

「え、まだ健康診断うけてないの?」って言われない?

はい大正解ヾ(≧▽≦)ノ! 健康診断はお早めにお願いします★(予約だけでもいいから……はやめに対応……!懇願)

「5年後、10年後のキャリアだけじゃなく、30年後も考えよう」メディアサービス部 部長 鈴木利夫 インタビュー

0

メディアサービス部(以下、MS部) 部長 鈴木利夫さんのインタビューです。「5年後だけじゃなく30年後のキャリアを面接で訊くのは、本気で考えてほしいからですよ」と語る鈴木さんに、部のこと、そして採用面接のことを中心に話を聞きました。(2020年12月 取材)

鈴木 利夫
メディアサービス部 部長
2011年 入社
映画を観ることが好き。最近すごかった映画は『KILLER SOFA』。

メディアサービス部は「職人」が多い部署

―― アピリッツご入社の経緯を教えてください

詳しくは言えないのですが、もともとは通信系の研究機関に長く関わっていました。そこで新しい通信サービスの仕様を作ったり、自分でプログラムを書いたり、開発会社に発注したり。

―― つまり元々はエンジニアだったのでしょうか?

“開発現場よりのプロジェクトマネージャー”がより適切な職種だったと思います。複数のプロジェクトに同時に参加して、過去の経験値をもとに「そもそもこういう要件でしたよね?」「ここ直したほうがよくないですか?」などと相談するんです。

自分で開発することもあれば、開発を別の会社にお願いすることもありましたし、いろんなレイヤーの仕事に関わって、管理や調整ごとを引き受けていました。

で、いろいろあって、知人の紹介でアピリッツに参加しました。

―― メディアサービス部はどういうチームですか?

私達はメディアに関連したサービスやWeb全般の仕事はなんでもやります。で、MSは「ザ・職人!」といった感じのチームです。技術を深堀りしていく人が多いですね。他の部署と連携しながら仕事をするメンバーもいます。

―― 鈴木さんは、どういうふうにMS部を率いていますか?

(しばらく腕を組んで考えたのち)あまり口を出さないようにしています。自分たちで考える力を身につけてほしいからです。“自走力”ってよく言われる言葉ですよね。自走するためには、経験するしかありません。ですから、口は出さずに見守っています。

這い上がる根性を持っている人は伸びる

―― どんな人が伸びていると感じますか?

「伸びる=技術力を高めること」だとするなら、身もふたもないことを言いますと、「伸びたい」と思って動けるひとが伸びます。

もちろん、伸びないひとだって何も考えていないわけじゃなく、「まずいな」「置いていかれるな」と認識しているはずです。でも「どうやったら追いつくのか」「どう動けばいいのか?」を考えて動けない。

こういうことって、他人に教わったからどうにかなるものでもないと考えています。誰かの話を聞いたり、本を沢山読んだからって、よいコードが書けるわけないんです。ラーメン1000杯食べたってラーメン屋にはなれないのと同じ。ラーメン屋になりたいんだったらラーメンを作る以外ないです。

だから、コードも書かないとうまくなりませんし、自分でやらないとできないんです。

自分の場合、若いとき最初に就いた仕事って、製造する会社さん向けに仕様を作ることだったんです。で、上司に見せると「ダメ」とだけ言われる。ひたすら直して提出して、また「ダメ」って言われて、また直して……「どこがダメなんだ?」って当然ムカつきますよ。で、ムカつくから「次こそは!」って頑張る。

最後にやっと受け取ってもらえたんですが、そのときも一言「センスねえな」って(笑)。やっぱりムカつく!(笑)で、「次はもっと良くしてやる!」って燃えるんです 。こんなやりかたが今の時代と合ってるかは、はなはだ疑問です。ただ、這い上がる根性を持ってる人は必ず大きく成長します。

話すと優しい鈴木さん。(撮影のためにマスクを外しています)

―― では、どんな人に来てもらいたいですか?

職人も必要ですが、同時に、職人ではない方も必要だと思っています。たとえば、昨今話題になっているDX(デジタルトランスフォーメーション)推進をおこなう場合、DXマネージャーは必須の存在です。

もしDXマネージャーがいないままプロジェクトが始まると、「DXを技術で解消しましょう」と動く実行部隊だけで終わってしまうんです。「どういう技術で、こんなDXを実現しましょう」というお話を、お客様と会話できる人が必要です。

私達は「ものを作る」ことを中心とする人が多い組織ですから、これから先は”旗振り役”な方にも今よりもっと沢山来ていただいて、よりスケールアップしていきたいです。

「5年後のキャリアはわかったよ。じゃあ、20年後、30年後どうしてたい?」

―― 鈴木さんは採用面接でどういうところを気にしますか?

その方の立ち位置によって視点を変えています。

中途採用の場合は、それまでのお仕事と、当社でやりたいことを伺って「じゃあ、この人は本当にアピリッツで長く働いていただけるか?」と考えます。スペシャリストを志向する人ならば、もちろん技術を重視します。

第二新卒の場合は、面接の時点での技術の高さは問いません。自分の将来を考えているかどうか、また、自分のレベル感をどのように把握されているかをよく質問します。

「チームを率いたい」と志望する人が、いざ現場に入ったら自分よりはるかに技術が高い”ザ・職人”たちの集団が待ち構えているわけですから、そりゃ大変です。そのあたりのギャップや覚悟がどのくらいあるかを冷静に話し合うことが大事だと思います。あと、夢も希望もなく入っても成長はむずかしいですし、楽しくないですから、何をしたいのかは知りたいですね。

最近はプログラミングスクール出身者もアピリッツに入社してくれています。彼らは勉強熱心で根性があります。ですから、これから大きく伸びていくだろうなと感じています。

最後に、新卒。新卒はいろんな方が応募してくださるので、会社的に合っていそうか、技術に興味があるかを重視します。そうじゃないと仕事はつらくなるでしょうし、本人もつらいですからね。

―― 最近入ったプログラミングスクール出身者の方が、採用面接時に「5年後、10年後のキャリア像は?」に加えて「じゃあ、20年、30年後は?」と鈴木さんに質問されてびっくりしたと聞きました。

あれね、冗談めかして質問していますが、30年後をどう思っているかはホントに知りたいし、考えてほしいんですよ。だから同じことを部のメンバーにも必ず訊いています。定年を迎える頃に何をしてたい? コードを書いてると本気で思っている? それって結構しんどくないですか? じゃあどうする? って。

―― では、鈴木さんは定年頃に何をしていたいですか?

そりゃもう、気持ちよくスパッと仕事を辞めたい(笑) 仕事を続けるなら、コンサルをやります。

―― ありがとうございました! インタビューの前に「俺の話なんてあんまりおもしろくないよ~」っておっしゃってましたが、おもしろかったです

そう? 書けない話ばっかりじゃなかった? 「ここだけの話」ってのも色々あるので、それはみなさん直接聞きにきてください(笑)

関連記事:アピリッツのその他の役員インタビュー

【IE11対応】背景画像のsvgを自由に色変えしたい

0
いろいろな矢印
矢印はたくさん使います

デジタルビジネス部所属Webデザイナーの黒須です。

SCSSを利用して、CSS(background-image)にSVGファイルを指定し、SVGらしくアイコンの色変えをサッと実現する方法を紹介します。

第一章 
SVGファイルそのものを整えてから

色変えするしないにかかわらず、SVGファイルの中身を理解し、気を配りましょう。

1.  SVGファイルを最適化

見た目は問題がなさそうなSVGファイル…
しかし

  • 隠れた不要なレイヤー
  • 要らない空パス
  • パスが閉じていない

など、データとして問題がないかチェックします。

Illustratorで作業

  1. 不要な隠しレイヤーなどを全て削除
  2. パスをアウトライン化
  3. 同じ色は複合パスでまとめる(cmd + 8)

複合パスの必要性

同じ色(fill1つで指定)のパスは1つにまとめます。
また複合パスでまとめることでデータを軽量化できます。
必要な物だけ残しシンプルでわかりやすいデータを目指します。

例えばこのような2つの>の字でデザインされた矢印アイコンは、複合パスにできます。

複合パスにせずそのまま書き出した場合、
SVGの中身(テキストデータ)はこんな感じ ※テキストエディタで開く

<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 492 492" style="enable-background:new 0 0 492 492;" xml:space="preserve">
<g><polygon points="69.8,0 0,69.8 176.2,246 0,422.2 69.8,492 315.8,246"/></g>
<g><polygon points="246,0 176.2,69.8 352.4,246 176.2,422.2 246,492 492,246"/></g>
</svg>

<g></g>が2つで、>の字パスが2つ描かれていることがわかります。

複合パスにした場合

<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"viewBox="0 0 492 492" style="enable-background:new 0 0 492 492;" xml:space="preserve">
<path d="M69.8,0L0,69.8L176.2,246L0,422.2L69.8,492l246-246L69.8,0z M246,0l-69.8,69.8L352.4,246L176.2,422.2L246,492l246-246L246,0z"/>
</svg>

パスが1つになりました。
この1つのパスに対して、fillでカラー指定すれば一発で色が変えることができます。
(パスが複数ある場合それぞれfillを記述しなければならないため余計な手間が増えます)

なおここまでの作業は、コーディングに渡す時点で完了していることが望ましいです。
隠れたレイヤーやパスが本当に要らないものかジャッジするのは作成者(デザイナー)の仕事です。
完成したファイルを次の工程(コーディング)に渡しましょう!
色変えを前提に作成している…などデザイン時に考慮している部分もしっかり共有しましょう。

2. SVGOMGでさらにダイエット

Adobe系・FigmaなどアプリからSVGを書き出した状態では、Web掲載時には必要ない記述が含まれているため、削除してファイルサイズを軽減します。
https://jakearchibald.github.io/svgomg/
ありがたい「SVGOMG」というWebサービスに、サッと湯通しします。
初期設定でひとまず問題ありません。

llustratorで書き出したままのファイル

<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 563.56 543.71">
 <g id="レイヤー_1" data-name="レイヤー 1">
  <g id="Layer_1" data-name="Layer 1">
   <path d="M77.14,0,0,77.14,194.72,271.86,0,466.58l77.14,77.13L349,271.86ZM291.7,0,214.56,77.14,409.28,271.86,214.56,466.58l77.14,77.13L563.56,271.86Z"/>
  </g>
 </g>
</svg>

SVGOMGを通したファイル

<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 563.56 543.71">
  <g data-name="レイヤー 1">
    <path d="M77.14 0L0 77.14l194.72 194.72L0 466.58l77.14 77.13L349 271.86zM291.7 0l-77.14 77.14 194.72 194.72-194.72 194.72 77.14 77.13 271.86-271.85z" data-name="Layer 1"/>
  </g>
</svg>

すっきりしました。
もっと複雑なファイルであればその効果は歴然です!

3. エディタでソースを確認する

SVGOMGしたファイルに問題がないか、まず確認します。

中身を理解する必要がありますし、この一手間の積み重ねが美しいサイトを作ります。
datan-name<g></g>、id・height・widthなど、使用する明確な予定が無ければ削除します。
(ie11で表示が豆粒になるバグが発生した場合はwidth/heigthを入れると解決するパターンがあるため適宜残してもよいです)

シンプルなSVG 理想の形

<svg xmlns="http://www.w3.org/2000/svg" viewBox="〇〇〇〇">
  <path d="〇〇〇〇"/>
</svg>

この形を目指します。
エディタでファイルを開き、余計な部分を削除します。

最終的なファイル

<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 563.56 543.71">
  <path d="M77.14 0L0 77.14l194.72 194.72L0 466.58l77.14 77.13L349 271.86zM291.7 0l-77.14 77.14 194.72 194.72-194.72 194.72 77.14 77.13 271.86-271.85z"/>
</svg>

シンプルで気持ちがいいです。
これでSVGファイルの準備ができました。

第二章 
いよいよコーディング SCSSでパターン作成

SCSSで簡単にコーディングするために、mixinを作成し使いまわします。
ひとまず完成形はこちらです。

SCSSでの使い方

.btn-A {
  @include svg-arrow(re-color($white));
}

.btn-B {
  @include svg-arrow(000);
}

$white(サイトカラーを格納している変数)や、000(カラーコード)を指定し、その色のSVGを呼び出している感じがありますね。

CSSコンパイル結果

.btn-A {
  background: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 563.56 543.71'%3E%3Cpath fill='%23ffffff' d='M77.14 0L0 77.14l194.72 194.72L0 466.58l77.14 77.13L349 271.86zM291.7 0l-77.14 77.14 194.72 194.72-194.72 194.72 77.14 77.13 271.86-271.85z'/%3E%3C/svg%3E") 50% 50%/100% 100% no-repeat;
}

コンパイルすると、この面倒なSVGデータを自動で書き出してくれます。
fill=’%23ffffff’(fill=#fff) 白のカラーコードがちゃんと入っています。

では、このmixinの作り方、具体的に何をしているのか解説します。

1. テンプレートとなるmixinを定義する

mixinテンプレート

@mixin svg-〇〇() {
  background: url("data:image/svg+xml;charset=utf8,△△")
  50% 50% / 100% 100% no-repeat;
}

mixinはこんな感じです。↑コード内の

〇〇 = mixinに好きな名前をつける(接頭語を「svg-」とするmyルール策定)
△△ = SVGのテキストデータを記述する(次の項目で詳しく解説します)

このmixinを複製し、アイコンのストックを作っていくイメージです。

2. URLエンコード(IEのため)

SVGのテキストデータはそのままではIEが理解できないので、URLエンコードします。
https://yoksel.github.io/url-encoder/
※シングルクウォーテーションにする必要があります
(エンコーダーが一緒にやってくれます便利〜)
※SVGファイルをエディタで開いてください

SVGテキストデータを

<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 563.56 543.71">
 <path d="M77.14 0L0 77.14l194.72 194.72L0 466.58l77.14 77.13L349 271.86zM291.7 0l-77.14 77.14 194.72 194.72-194.72 194.72 77.14 77.13 271.86-271.85z"/>
</svg>

エンコードすると、こうなります

%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 563.56 543.71'%3E%3Cpath d='M77.14 0L0 77.14l194.72 194.72L0 466.58l77.14 77.13L349 271.86zM291.7 0l-77.14 77.14 194.72 194.72-194.72 194.72 77.14 77.13 271.86-271.85z'/%3E%3C/svg%3E


3. テンプレートに挿入

エンコードしたSVGのテキストデータを、テンプレート「△△」部分に挿入します

@mixin svg-arrow() {
  background: url("data:image/svg+xml;charset=utf8,△△")
  50% 50% / 100% 100% no-repeat;
}
@mixin svg-arrow() {
  background: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 563.56 543.71'%3E%3Cpath d='M77.14 0L0 77.14l194.72 194.72L0 466.58l77.14 77.13L349 271.86zM291.7 0l-77.14 77.14 194.72 194.72-194.72 194.72 77.14 77.13 271.86-271.85z'/%3E%3C/svg%3E")
  50% 50% / 100% 100% no-repeat;
}

色を指定する「fillの指定」を path と d=”〜” の間あたりに追加します。

@mixin svg-arrow() {
  background: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 563.56 543.71'%3E%3Cpath fill='%23ffffff' d='M77.14 0L0 77.14l194.72 194.72L0 466.58l77.14 77.13L349 271.86zM291.7 0l-77.14 77.14 194.72 194.72-194.72 194.72 77.14 77.13 271.86-271.85z'/%3E%3C/svg%3E")
  50% 50% / 100% 100% no-repeat;
}

fillの指定

fill='%23ffffff'

#ffffffを直接指定しています。
「#」もエンコードする必要があるので「%23」にします。

これで、白色の矢印アイコンのmixin「svg-arrow()」ができました。
さらに、色の変更を簡単するため、ひと工夫します。

4.  fillを変数にして、気軽に色変える

@mixin svg-arrow($color: 000) {
  background: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 563.56 543.71'%3E%3Cpath fill='%23#{$color}' d='M77.14 0L0 77.14l194.72 194.72L0 466.58l77.14 77.13L349 271.86zM291.7 0l-77.14 77.14 194.72 194.72-194.72 194.72 77.14 77.13 271.86-271.85z'/%3E%3C/svg%3E")
  50% 50% / 100% 100% no-repeat;
}

変数を定義し、svg-arrow($color: 000)  例:000をデフォルトに定義

// Before
@mixin svg-arrow() { 〜 }

// After
@mixin svg-arrow($color: 000) { 〜 }

mixinの中で受け取っています。fill=’%23#{$color}’

// Before
fill='%23ffffff'

// After
fill='%23#{$color}'

使用するときは、

.btn-B {
  @include svg-arrow(fff);
}

違う色の指定が簡単です。

5. サイトカラーを変数で管理している場合

@include svg-arrow($red);

このように、変数で管理しているカラーを使いたいですね。
しかし、このままではコンパイルエラーになります。

変数の中身次第ですが、カラーコード用の「#」が入っているため問題が起こります。

$red: #e94527;

したがって、データ的に「#」を削除するfunctionを作成し、正しい形に直せば利用できます。

カラーコード#抜き関数

@function re-color($code) {
  @return str-slice("#{$code}", 2);
}

カラーコード入りの変数を使いたいときは、この「#抜き関数」で補完する感じです

//変数
.btn-A {
  @include svg-arrow(re-color($red));
}

//カラーコード #付きの場合
.btn-B {
  @include svg-arrow(re-color(#fff));
}

//カラーコード数値のみなら、re-color不要
.btn-C {
  @include svg-arrow(fdfdfd));
}

カラー「$red」を指定して、SVGを呼び出すことができました。

また、アイコンの初期カラーは全て変数の「$main」カラーにするmyルールを定めた場合、
mixin側にも「#抜き関数」を使用します。

@mixin svg-arrow($color:re-color($main)) {
  background: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 563.56 543.71'%3E%3Cpath fill='%23#{$color}' d='M77.14 0L0 77.14l194.72 194.72L0 466.58l77.14 77.13L349 271.86zM291.7 0l-77.14 77.14 194.72 194.72-194.72 194.72 77.14 77.13 271.86-271.85z'/%3E%3C/svg%3E")
  50% 50% / 100% 100% no-repeat;
}

最後に

SVGの色パターンをCSSだけで増殖させる方法でした。
簡単………しっかり解説すると長くなってしまいました。

サイトの規模・パターン数によってこれがベストではないことをすでに感じていますが、何かお役に立てたらハッピーです。

ベイズ統計学の世界への誘い

0

はじめに

データイノベーション部の浅田です。

統計学のひとつにベイズ統計学というものがあります。ベイズ統計学は現代の機械学習において、重要な一角を占めています。

例えば、スパムメールかどうかを判定する機械学習の手法にナイーブベイズという手法があります。これはメールの文面に記載される単語について、スパムメールにその単語が出現する確率を学習しておき、判定対象のメールに書かれた単語から、そのメールがスパムメールかどうかを判定するような仕組みになっています。その際に、ベイズ統計学の根本をなすベイズの定理が使われています。

また、機械学習においては、パラメータの最適値を探す作業が度々発生します。例えば、ハイパーパラメータと呼ばれる人間が指定しなければいけない値がありますが、その値の最適値を探索する必要があったりします。そのような場合に、取りうるすべての値を試すのは時間がかかるので、効率的に探索する必要があります。そのような時に最適解に導く手法の一つに、ベイズ最適化というものがあり、その名の通りベイズ統計学の仕組みが使われています。

このように、機械学習についても重要なファクターであるベイズ統計学の理論についてご紹介したいと思います。

ベイズ統計学

ベイズ統計学では、確率は事象における直観的信頼度として表現されます。「事象の直観的信頼度」を平たい表現にすると、事象が起こると信じる度合い、と言えます。ベイズ的な考え方においては、信じる度合いとしての確率はデータ(確認された事実)によって変動します。その更新はベイズの定理によってなされるため、ベイズ更新と呼ばれます。

ベイズの定理

ベイズの定理は以下のような式になります。

\begin{aligned}P(H \mid D ) = \frac {P(D \mid H) \times P(H)}{P(D)} \end{aligned}

要素を分解してみましょう。$P$という記号は確率を表します。$P(H)$は$H$という事象が起こる確率と言う意味です。例えば、「真っ当な」サイコロであれば1が出る確率は$\frac{1}{6}$となるので、

\begin{aligned}P(サイコロで1が出る) = \frac{1}{6}\end{aligned}

となります。

$P(H \mid D)$は、条件つき確率と呼ばれるもので、$D$という条件が満たされた場合に$H$が起こる確率となります。

例えば、「真っ当な」サイコロで1が出る確率は先ほどの通り$\frac{1}{6}$となりますが、そこにサイコロの目が奇数だった、というデータ($D$)があらかじめ観測されたとします。そうすると、その条件の際に1になる確率は1,3,5のどれかに絞られるので、$\frac{1}{3}$となります。

つまり、

\begin{aligned}P(サイコロで1が出る \mid 出目が奇数) = \frac{1}{3}\end{aligned}

ということですね。

これをベイズの定理に当てはめてみましょう。

\begin{aligned} P(サイコロで1が出る \mid 出目が奇数 ) &=\frac {P(出目が奇数 \mid サイコロで1が出る) \times P(サイコロで1が出る)}{P(出目が奇数)}\\ &=\frac {1 \times \frac{1}{6}}{\frac{1}{2}}\\ &=\frac {1}{3} \end{aligned}

これは、ベイズ的な解釈をすれば「出目が決まっていない状態でサイコロの1の目が出ると信じていている確率である$\frac{1}{6}$が、出目が奇数であるという新たなデータを得たことで$\frac{1}{3}$に更新された(確信度があがった)」ということになります。これがベイズ更新の流れになります。

これだけだと回りくどいことをやっているように感じるかもしれませんが、ベイズの枠組みの面白いところは、この枠組みを主観的なパターンに応用できるところです。

イカサマサイコロ?

例えば、先ほどから「真っ当な」サイコロと表現していましたが、もし5回投げて5回とも1が出るという事実を目にした場合、このサイコロを真っ当なサイコロと思うでしょうか?5回も1が出たら「なにか変だぞ?」と思うのではないでしょうか。

その時の確信度の変化をベイズの定理でモデル化してみます。

\begin{aligned} P(イカサマ \mid 5回連続1が出る ) &=\frac {P(5回連続1が出る \mid イカサマ) \times P(イカサマ)}{P(5回連続1が出る)} \end{aligned}

この時、ベイズ統計では、

  • $P(イカサマ \mid 5回連続1が出る )$を事後確率
  • $P(5回連続1が出る \mid イカサマ)$を尤度(ゆうど)
  • $P(イカサマ)$を事前確率
  • $P(5回連続1が出る)$を周辺尤度

と表現します。

事前確率、事後確率、尤度、周辺尤度

ベイズの定理の再掲となりますが、

\begin{aligned}P(H \mid D ) = \frac {P(D \mid H) \times P(H)}{P(D)} \end{aligned}

ベイズ更新においては、上記の$P(H \mid D)$は「$D$という事象(データ)が観測された事後にHという事象が起こる確信度」となり、$P(H)$は「$D$という事象(データ)が観測されるよりも事前に$H$という事象が起こる確信度」となります。そのため、$P(H \mid D)$を事後確率、$P(H)$を事前確率と呼びます。ベイズ更新の枠組みでは、この事前確率を主観で決めてしまって構いません。なので、人間が事前知識として持っている確信度を当てはめてしまって問題ありません。データを観測することで、事前確率はデータを反映した事後確率に更新されることになります。

なお、ここまで$H$という文字を使っていましたが、これはHypothesis(仮説)の頭文字を表しています。事象$H$が起こる確信度とは、言い換えれば、事象$H$が起こるという仮説を信じる度合いと見なせます。つまりベイズ更新とは、観測されたデータによって仮説に対する確信度がどう更新されるか、ということをモデル化しているということになります。

事前確率がどのように事後確率に更新されるかは、$P(D\mid H)$と$P(D)$の比である$\frac {P(D\mid H)}{P(D)}$によって決まります。分子の$P(D \mid H)$を尤度(ゆうど)と呼びます。仮説$H$が正しいとした時にデータ$D$が観測される尤もらしさ、つまり「データが持つ仮説$H$に対する説得力」を表します。分母の$P(D)$は「データが一般的に観測される確率」で、周辺尤度などと呼ばれます。

$\frac {P(D\mid H)}{P(D)}$という値は$P(D \mid H)$が$P(D)$に比べて大きければ大きいほど値は大きくなります。言い換えると、データ$D$が一般的に観測される確率よりも事象$H$が起きた時にデータ$D$が観測される確率が高い事象であればあるほど大きくなります。したがって、観測されたデータ$D$が仮説$H$に対して固有であればあるほど、事前確率は確信度の高い事後確率に更新されることになります。

例えば、先ほどのイカサマサイコロの例であれば、5回連続1が出ることは真っ当なサイコロではレアケース=一般的にありえないであるため、イカサマがある時のほうが観測される確率が高いと判断されます。その結果、「イカサマサイコロかも」という思いはより確信度が高くなるでしょう。

続・イカサマサイコロ?

ベイズ統計モデリング

先ほどの5回連続で1が出た際に、「イカサマがあるんじゃないか?」と主観が変化することをベイズ統計を使ってモデリングしてみます。

今回は、

仮説$H$ =「サイコロで1が出る確率が6回に1回である」

とします。事前確率$P(H)$は仮説$H$に対する確信度ということになります。さて、その確信度をどう定義するかですが、ベイズ統計モデリングの特徴として、事前確率や事後確率を定義する際に確率分布を用いる点があります。

確率分布を用いることで、確率をより直観的に表現できます。

その確率分布に、α回成功してβ回失敗したときに、その成功確率pの分布を表現できるベータ分布というものがあります。

式の定義としては、

\begin{aligned} f(p;α,β) &=\frac {p^{α-1}(1-p)^{β-1}}{\int_0^1t^{α-1}(1-t)^{β-1}dt} \end{aligned}

となります。例えばα=5, β=5を指定すると、5回成功して5回失敗する場合の統計的な成功率の分布を表現することができます。式だけだと何ぞやって感じだと思いますので、ベータ分布をいくつか図示してみます。

上図のように、α=5, B=5であれば成功率0.5付近が確信度が一番高くなっている形状になり、α=3, β=7だと成功率0.3付近が一番確信度が高くなっています。このようにして信頼度の分布を表現できるのが、確率分布を利用することによるメリットの一つです。なお、合計が10である必要はなく、任意の1以上の整数の組み合わせを指定できます。

ちなみに、α=5, β=5、α=10, β=10を指定した場合、成功率の確信度が高くなるのは0.5付近で同じですが、形状が少し異なります。

これはα=10, β=10のほうが「成功率が0.5付近であること」をより確信していることを表しています。なので、αとβの比は同じでも、合計数が大きくなればなるほど、成功率に対してより確信度が高い状態となります。これはデータが多ければ多いほど、真の値に近くという統計学の基本定理大数の法則とも合致します。

今回はこのベータ分布を事前確率として用います。今回のケースでは1が出ることを成功として定義して、1以外が出ることを失敗として定義すると、サイコロで6回に1が出る確率の分布を表現できます。今回は6回に1回ぐらい成功するはずだということで、α=2, β=10(12回投げて、2回は1が出て、10回はそれ以外が出る)としておきましょう。

なので事前分布$P(H)$は、以下のようになります。

\begin{aligned} f(p;2,10) &=\frac {p^{2-1}(1-p)^{10-1}}{\int_0^1t^{2-1}(1-t)^{10-1}dt} = \frac {p(1-p)^{9}}{\int_0^1t(1-t)^{9}dt} \end{aligned}

次に尤度です。尤度は仮説が正しいとした場合に、データが得られる確率です。つまり今回の場合、成功確率が6回に1回だったとして、5回中5回とも1の目が出る確率になります。このような時に使える分布として二項分布というものがあります。

\begin{aligned} f(k;n,p)=_n C _k p^k(1-p)^{n-k}=\frac{n!}{k!(n-k)!}p^k(1-p)^{n-k} \end{aligned}

この式で、kは成功回数、nは試行回数、pは成功確率となります。成功確率がpの時に、5回中5回成功する確率は、上記式に当てはめれば、

\begin{aligned} f(5;5,p)=\frac{5!}{5!(5-5)!}p^5(1-p)^{5-5}=p^5 \end{aligned}

となります。したがって$p^5$が今回の尤度です。

最後に、周辺尤度です。周辺尤度は尤度と事前確率分布との積であらわされる関数について全ての確率変数pを入力とした時の出力の合計値として算出されます。従って、事前確率分布の確率変数が取り得る値である0から1で関数を積分した値となります。

つまり、周辺尤度を式で表すと以下のようになります。

\begin{aligned} \int_0^1\frac {p(1-p)^{9}p^5}{\int_0^1t(1-t)^{9}dt}dp = \int_0^1\frac {p^{6}(1-p)^{9}}{\int_0^1t(1-t)^{9}dt}dp \end{aligned}

したがって求めるべき事後分布である$P(H \mid D)$は

\begin{aligned}P(H \mid D) =\frac {\frac {p^{6}(1-p)^{9}}{\int_0^1t(1-t)^{9}dt}}{\int_0^1\frac {p^{6}(1-p)^{9}}{\int_0^1t(1-t)^{9}dt}dp}\end{aligned}

…(´・ω・`)

こんなの手で計算したくないですよね(少なくとも自分はやりたくありません)。ということで、python先輩にお任せします。

ここまでの計算をpythonのコードに落とし込むと、

import scipy.integrate as integrate


# 事前確率分布
p_h = lambda p: p * (1-p) ** 9 / integrate.quad(lambda t: t * (1-t) ** 9, 0, 1)[0]
# 尤度
p_d_h = lambda p: p ** 5
# 周辺尤度
p_d = integrate.quad(lambda p: p_d_h(p) * p_h(p), 0, 1)[0]
# 事後確率分布
p_h_d = lambda p: p_d_h(p) * p_h(p) / p_d

scipy.integrate.quad()は、第一引数の関数を、第二引数から第三引数の区間で積分してくれる関数です。結果は積分結果と誤差とのtapleになっています。なので、[0]を指定することで積分結果を取り出しています。

これで事後確率の確率分布が求まりました。事前確率の確率分布と尤度とともに図示して見ましょう。

import matplotlib.pyplot as plt
import numpy as np


# 確率変数
p = np.arange(0, 1.01, 0.01)
# グラフの準備
fig = plt.figure()
ax = fig.add_subplot(111)
plt.title("ベイズ更新")
plt.xlabel("成功率")
plt.ylabel("確信度")
# 事前確率分布
plt.plot(p, p_h(p), 'k--', color='g', label="事前確率")
# 事後確率分布
plt.plot(p, p_h_d(p), color='b', label="事後確率")
# 凡例
plt.legend(loc='lower right', borderaxespad=1, fontsize=12)
ax.twinx()
plt.ylabel("尤度")
# 尤度
plt.plot(p, p_d_h(p), 'k--', color='r', label="尤度")
# 凡例
plt.legend(loc='upper right', borderaxespad=1, fontsize=12)

緑の破線で描かれている事前確率分布は0.15付近、つまりおよそ$\frac{1}{6}$付近の確信度が高くなっているのが見て取れます。これはデータを観測する前には、真っ当なサイコロで1が出る確率である$\frac{1}{6}$付近がサイコロで1の目が出る成功率だと信じていたことを示しています。

そして、赤の破線が尤度です。$\frac{1}{6}$付近の尤度は極めて低くなっています。ほぼ0です。これは5回連続で1の目が出ることは、1の目で出る成功率が$\frac{1}{6}$だとしたら、ほとんどありえないことを表します。

ベイズ更新の結果である、青の実線で描かれた事後確率分布では、成功率$\frac{1}{6}$付近の確信度はかなり下がっています。その代わり事前確率分布ではかなり確信度が低かった0.4以上の成功率に対する確信度が上がっています。つまり、データを観測した結果、成功率は$\frac{1}{6}$付近ではなく、もっと高い成功率なのでは?と考えるようになったことを表しています。

なお、今回のように確率分布における確率変数(今回の場合は成功率)が連続値である場合には、確率分布の関数を確率密度関数と言います。一方、二項分布などの場合には、確率変数が離散値となるので確率質量関数などと言います。確率密度関数においては、確率変数の値で積分をおこなうことによって、特定の確率変数の範囲における確率を計算することができます。例えば、今回のケースで言えば、サイコロの1の目が出る確率が0.4以上である確信度を計算することができます。

# 事前確率の0.4以上の成功率に対する確信度
print(integrate.quad(p_h, 0.4, 1)[0]) # 0.030233088000000016
# 事後確率の0.4以上の成功率に対する確信度
print(integrate.quad(p_h_d, 0.4, 1)[0]) # 0.5271741135912963

上記の結果から、0.4以上であることの確信度は0.03(=3%)から0.53(=53%)に跳ね上がったということになります。このようにピンポイントの確率変数だけでなく範囲を指定した確率変数に対する確信度を計算しやすい、というのも確率分布を使うメリットですね。

別解:scipy.statsにある確率分布を利用する

さて、上記では確率分布の定義式に、パラメータを当てはめて計算結果を求めたわけですが、pythonのscipyライブラリにあるstatsモジュールには様々な確率分布の計算を楽にしてくれる関数があります。

それを使うと先ほどの事後確率の計算は以下のようにも書けます。

import scipy.stats as st
import scipy.integrate as integrate


# 事前確率分布
p_h = lambda p: st.beta.pdf(p, a=2, b=10)
# 尤度
p_d_h = lambda p: st.binom.pmf(p=p, n=5, k=5)
# 周辺尤度
p_d = integrate.quad(lambda p: p_d_h(p) * p_h(p), 0, 1)[0]
# 事後確率分布
p_h_d = lambda p: p_d_h(p) * p_h(p) / p_d

scipy.stats.betaはベータ分布、scipy.stats.binomは二項分布を表します。beta.pdf()はベータ分布の確率密度関数を計算してくれる関数、binom.pmf()は二項分布の確率質量変数を計算してくれる関数になります。

上記の事前確率分布と尤度に使う組み合わせを変えてやれば、様々な確率分布を利用したベイズ更新に応用できます。

さらに別解:ベータ分布の性質の利用

なお、今回事前分布に利用したベータ分布は、尤度につかった二項分布と組み合わせた場合に、事後確率分布もベータ分布になります。尤度に対して、事前と事後の確率分布の種類が同じになる事前確率分布を共役事前分布と言ったりします。

そして、ベータ分布には便利な性質がもう一つあります。

それは、事前確率分布にベータ分布を使った場合、尤度にn回中k回成功した二項分布を使って事後確率分布を計算した結果と、事前確率分布のパラメータα, βに、それぞれ成功回数、失敗回数を追加したパラメータα+k, β+n-kを使って計算したベータ分布の結果とは一致するという性質です。

つまり、わざわざ二項分布をつかって尤度を計算したり、積分を行って周辺尤度を計算せずとも、事前確率分布のパラメータを調整するだけで、事後確率分布を得ることができます。

すなわち、今回のケースで求めた事後確率分布は以下のようにも求められます。

import scipy.stats as st


# 事前確率分布はα=2, β=10であり、
# 5回成功し、0回失敗したデータを観測したので
# αに2+5+7、βに10+0=10を指定する。
p_h_d = lambda p: st.beta.pdf(p, a=2+5, b=10+0)

事後確率分布は次のベイズ更新の事前分布として利用できる

以上でベイズ更新を使ってデータを観測した事後確率分布を求めることができました。そして、この事後確率分布はさらなるデータが観測された時の事前確率分布として使用できます。

つまり、さらにサイコロを振ったときにn回中k回1が出たデータを観測したのであれば、

import scipy.stats as st


p_h_d = lambda p: st.beta.pdf(p, a=7+k, b=10+n-k)

でさらなる事後確率分布を求められます。そのようにしてどんどんデータを集めていけば、その確信度を示す確率分布の密度は真の値付近に集中していきます。密度が集中している、つまり確信度が高いということは、データから判断するとその付近が求めたい値だと判断できるということです。

それがおよそ$\frac{1}{6}$に近づけば、そのサイコロは真っ当なサイコロであると判断できるでしょうし、それ以外の値に近づけば真っ当なサイコロではないと判断できるでしょう。

このような仕組みで、未知のパラメータを推定する手法をベイズ推定と呼びます。

おわりに

ベイズ統計学の世界の一端を垣間見ていただけたなら幸いです。冒頭でお伝えした機械学習に対する利用だけなく、ベイズ統計を利用することで回帰分析や仮説検定、時系列モデル分析など、様々な分析を行うことも可能です。またの機会にそれらについて、ご紹介できればと思います。

関連:ビジネスはAIの夢を見るか~AIがビジネスにもたらす価値~

受託開発における企画書の使い方

0

こんにちは。ゲームデザイン部のディレクターの江中です。
昨年に中途入社しましたが、それまでは自社開発の経験ばかりで、アピリッツで初めてゲームの受託開発を経験しました。

この記事では、ゲームディレクターの私が受託開発を進めていくにあたって、企画書を活用して後工程における問題発生防止のために工夫した点を紹介させていただきます。

ゲームの受託開発の流れ

企画書の話をする前に、前提としてゲームの受託開発の流れをご説明いたします。ゲームとはいってもソフトウェアであるため、基本は通常のソフトウェア開発の流れとなります。ソフトウェア開発には様々な手法があると思いますが、規模が大きいゲームの受託開発においては契約を分かりやすくするために、期間(いつまでに)と成果物(何をつくるのか)を明確に定めやすいインクリメンタル開発をすることが多いように思います。インクリメンタル開発とは、プリプロダクション版フェーズやα版フェーズといった形で期間と実装内容を定めて、そのフェーズごとに徐々に機能を追加していく形で実装していく方式です。大雑把なイメージとしては、次のような図となります。

インクリメンタル開発では機能ごとに開発していくため、全てが完成したときのUXを確認できるのが最後になり、大きなリスクがあります。また仕様変更があった場合に、細部まで作り込んでいるとその分多くの工数が無駄になってしまうことがあります。

インクリメンタル開発をより深く理解するために、よく比較されるイテレーティブ開発をご紹介いたします。上記のインクリメンタル開発の弱点を克服しようとしたのがイテレーティブ開発です。イテレーティブ開発では最初は最低限の機能しか実装しませんが、徐々に機能を増強したり操作性を高めたりして洗練させていきます。個人的にはゲーム開発においては、全体のUXを把握しながら開発できるこちらの方法がより向いているように思います。大雑把なイメージを示しますと次のような図になります。

インクリメンタル開発の各工程

インクリメンタル開発ではどのように機能開発していくのかを確認してきましたが、続いて工程がどのように進むのかを見ていきましょう。ちょうど五月雨式にウォーターフォール開発を繰り返すイメージで、次の図のような方式となります。

上記の図では、テストは1つの工程として表されています。しかし、実務においては企画から実装までの幅広い工程の結果をテストしていく必要があるため、実際にはテスト工程はいくつかの工程に分かれます。上流の各開発工程に対応させてテスト工程を分割したものをV字モデルといいます。V字モデルを図にすると、次のようになります。

V字の左側が開発工程で、右側がテスト工程となります。各工程では、次のようなことを実施します。

  • 企画工程(要求定義)では、「なぜそれをやるのか」という目的(ゴール)を定義し、その要素(機能や施策)によって何を達成したいのかを決めます。
  • 設計工程では、企画で決めた要素をどのように作成するのかを決めます。
  • 実装工程では、決めた通りにつくります。
  • 試験工程では、設計で決めた通りの仕様になっているのかを確認します。
  • 検証工程では、企画で決めた目的を達成しているのかを確認します。

今回は特に、この企画工程の成果物である企画書の使い方について取り上げています。

企画工程で目的・ゴールを整理・共有していないと失敗しやすくなる

入社前に私が経験した自社開発プロジェクトにおいては、各機能や施策の目的はディレクターやプランナーの頭の中にあるので、詳細な企画資料がない状態で設計工程から進行していくということがありました。しかし、設計工程で共有されるのが具体的な機能仕様や施策内容だけだった際には、UXを作り込むデザイナーやエンジニアに目的が伝わらずに、ディレクターや担当プランナーが意図したものにならないこともありました。またプランナー間連携においても、例えば企画工程担当と設計工程担当のプランナーが異なるケースでは、企画工程で定めた目的に合わない内容の仕様書が、設計工程で作成されてしまうことがありました。

例えばキャラクターに「超必殺技」という要素を追加するといった場合に、ARPPU向上を目的にキャラを重ねてもらう施策として導入するのか、継続率向上を目的にキャラクターにパラメーター的な個性を付与してデッキ編成に創意工夫の幅を持たせる施策として導入するのかでは作るべき仕様が大きく異なります。しかし、企画工程で目的を定めていなかったり、設計工程担当プランナーがディレクターへの確認を怠ったりすると、キーワードだけで仕様作成が進んでしまって、目的と合わない仕様が作成されてしまうことがあったのです。

顧客と目的・ゴールを握り、後工程で確認できるように資料化する

自社開発にもある程度当てはまると思いますが、特に受託開発で何か要素を新規開発する際には、目的・ゴールを企画工程で企画書にまとめ、顧客と話し合い共通認識を持ってから設計工程以降を進めると社内外での調整がスムーズに行くように思います。企画書にどのKPI向上を目指すのか、あるいはどのような体験をつくろうとしているのかといったことを書いておき、いつでも参照できるようにしておくのです。

社内においては、まず設計工程担当プランナーは企画書を踏まえて仕様書を作成することができるようになります。また仕様書の完成後に、企画工程担当プランナーを含むレビュアーが、その仕様が実装されることで目的・ゴールが達成されるのかという視点で確認できるようになります。このときUXに詳しいデザイナーや、内部設計に通じたエンジニアが含まれていると、目的をより良く実現できる設計を提案してくれるかもしれません。そして仕様書レビューに参加できなかった実装担当のデザイナーやエンジニアも、企画書を読むことで目的を知ることができるため、実装上の内部的な作り込みも、より良くできるかもしれません。

社外、すなわち顧客においては、握った目的・ゴールの内容を、その後の設計工程の成果物であるソフトウェア仕様書や、検証工程で「企画で決めた目的を達成しているのか」を確認していただく際に基準として活用することができます。誰でも数ヵ月前の記憶は曖昧になりがちなので、どういった目的のために何をつくるのかということを定めた企画書を作成して残しておくと、認識違いが起こりにくくなります。

私が参加したプロジェクトでは、該当フェーズで新規実装した要素が多かったので、ゴール設定資料といった形で①新規実装要素、②その目的、③目的を達成したか否か、の3点を一覧にまとめてご確認いただくことで、比較的スムーズに検収していただくことができたと思います。具体的には次のようなイメージの表を用意し、顧客と該当フェーズで新規開発した要素について認識合わせをさせていただいた形です。

最後に

トヨタ式の鉄則として「前工程は神様、後工程はお客様」というものがあります。特にゲーム受託開発では契約の分かりやすさから、インクリメンタルなウォーターフォール開発に近い方式を採用することが多そうなゆえに、この鉄則が当てはまりやすいように思います。よってディレクターや企画工程を担当するプランナーは、後工程に大きく影響することを理解し、企画(要求定義、要件定義)の品質を高めていくことが求められるように思っています。

またゲーム開発においては実際にプレイしてみないとUXが分からない部分も少なくなく、顧客からインクリメンタル開発的な契約でありながらイテレーティブ開発のようなご要望をいただくこともあります。そういった個所を先回りして検知し、AdobeXDによるモックで念入りに確認したり、あらかじめブラッシュアップ期間に修正していくと方針を決めておいたりする先見性も必要になると思います。

私自身、過去の成功体験が異なるチームメンバーや顧客とどのように認識を合わせながら進めていくべきかを模索しながら進めた方法論となりますが、この記事が読んでいただいた方の一助になれば幸いです。

今年はオンライン開催! 2021年 新卒内定者 顔合わせ会

0

イベント開催やパーティーが難しかった2020年もそろそろ終わります。本来ならば実施していたはずの「内定式」も取りやめ……でも、アピリッツには今年もたくさんの内定者がいます。2021年4月の入社にむけて、内定者同士、そして会社と内定者のみなさんが、お互いを知る機会を設けたい。ということで人事企画部が「内定者顔合わせ会」をオンライン上で開催しました。(2020年12月 取材)

オンラインイベントを盛り上げるために

すでに内定者アルバイトとして仕事に参加しているメンバーもいますが、多くの内定者はオンライン上で初めてお互いの顔を見ます。緊張もするでしょうし、はたして盛り上がるのか? 盛り上げられるのか!? ……ということで、人事企画部の採用担当者からの渾身の前説。「拍手をしよう!」「リアクションはどんどん出していきましょう!」と呼びかけ、場をあっためました。

たぶん通常よりもテンション高め。

そして自己紹介。オンラインからの参加者もいれば、

笑顔がすてき

内定者アルバイトとして会社に来ている内定者からの挨拶も。

人事企画部も広報の私たちも、内定者の皆さんの意外な一面を知ることができました

自己紹介のあとはクイズをやってみたり……、

みんなでワイワイしながら会社とお互いのことを知っていきます。

会社にまつわるちょっとしたクイズを実施。アピリッツの代表取締役社長執行役員CEOの名前は和田順児です

Zoom越しでも明るく丁寧にコミュニケーションをかさねると、なんだか楽しくなってくるものなんですね。で、場があったまったかな……というタイミングで、数人の班にわかれてアピリッツの事業やサービス、会社の特徴について考えるグループワークをおこないました。

内定者アルバイトとして出社しているメンバーはアピリッツの会議室から顔合わせに参加

グループワークとそれぞれのチームの発表のあとは、オフィスの様子を見てもらうための社内見学ツアーも実施しました。これ、オフラインでも入社前に「こんな感じで働いてますよ」と見てもらうことがあります。それのオンライン版です。

ファンサを求める人の気持でのぞんだはず

事前に全社員に「オンラインで社内見学をおこなうのでよろしくね!」お知らせしていたので、オフィスにいる社員が手をふってくれました。ご協力ありがとうございました! 内定者のみなさん、4月にあえることを楽しみにしています!

Google スプレッドシートの便利関数-part1-

0

コンテンツデザイン部の江川です。

データを扱う際に皆さんは何を使っていますでしょうか。様々あるとは思いますが、多くがexcelかGoogle スプレッドシート(以下スプレ)のどちらかを使用していると思います。
excelとスプレどちらを使うにも利点がありますが、多くの方がスプレってクラウド版のexcelでしょ。くらいの認識なのではないでしょうか。
私も最初はそうだったのですが、実は結構excelとスプレって違うんです。
そこで今回はクラウド化の波に乗ってexcelからスプレに変えた方やちょっとしたデータをみんなで触れる方が便利だからとスプレを使用している方に、今日から使えるスプレならではの便利関数を紹介します。

1.ARRAYFORMULA

スプレといえばこれ!といった関数です。スプレを愛用している方々の中にはこの関数が使えるからスプレにしているという方も少なくないでしょう。
ARRAYFORMULAとは一つのセルの式を配列形式で表示する関数です。

という方にもわかりやすいように、言い換えると一つのセルの数式をそれ以下の行or列に適応する関数です
以下のように点数から成績の値を算出する数式をIFS文で90点以上ならA、50~89はB、31~49がC、それ以下は赤点と定義します。
C3に数式を入れるともちろんC3セルに結果が算出され、この式を下に伸ばすと数式も下に伸びていきます。

しかし、ARRAYFORMULA関数を同じセルに適用すると……

このように、IFSのみの場合だとB3と一つのセルしか指定できませんでしたがARRAYFORMULAを加えることによってB3:Bの範囲全ての結果がC3:Cに反映されるようになります。

イメージでは数式の中でセルを指定していた部分を範囲指定に変えることでARRAYFORMULA式が機能するようになります。もちろんB3:B50のように特定の範囲も指定できます。

これの何が便利かというと利点は2つあります。
・セルを下に伸ばさなくても自動で入力されること。
  →大したことないと思うかもしれませんが使ってみるとこれがすごく便利です。Excelで行っていた作業を単純に1段階減らすことになり、なおかつ漏れやミスが減ることが大きいです。

・計算処理が圧倒的に軽いこと。
  →外部の方とデータを共有する時などに大きなデータでも、この関数を使って軽量化することでお互いストレスフリーで作業することができます。逆にスプレを共有して大量のセルに参照数式が入っているととても重くなり、お互いの作業効率が落ちてしまうことになるので気をつけましょう。

こちらがARRAYFORMULAを使った数式です。

ARRAYFORMULA(配列数式または、非配列関数で配列を使用)
例:ARRAYFORMULA(IFS(~~~)

2.IMPORTRANGE

こちらはスプレッドシートを使いこなす上で非常に重要な関数となっています。

これは先ほどのARRAYFORMULAフォルダとは違うIMPORTRANGEというタイトルのスプレのA1セルにIMPORTRANGE関数を適用したものです。

別のスプレッドシートから値を参照できるわけですね。

この関数は
=IMPORTRANGE(“スプレッドシートキー”,”そのスプレの範囲指定”)
となります。
スプレッドシートキーというのはそのスプレのURLのことです。関数にはhttps://~から入っていますが、キー部分は1H7Uj~の部分なので本来であれば不必要ですがどちらでも問題はありません。

なので今回で一番スマートなのは
=IMPORTRANGE(“1H7Uj2vFP64dCYtaKI_cEm7zlc0mYEowD5J2d9tRBfj0″,”シート1!A:C”)
ですね。

Excelでも別のフォルダからの参照はできるのですが、スプレの大きな違いはクラウド管理だということ。
IMPORTRANGEで出されたデータは元のスプレの値をリアルタイムで持ってこれるのでやはり複数人で同じデータを触る際に便利です。

いちいちURLをコピペするのが手間な人向け小技

画像のようなリストを作って、B列のキーを使う予定のフォルダにIMPORTRANGEします。
そのフォルダで別シートを参照する際はセル指定でIMPORTRANGEが使えます。
=IMPORTRANGE(‘画像シートの名前’!B2,”参照元シート名!範囲”)

つまり=IMPORTRANGE( まで入力してセルをクリックするだけでURLを入力しなくてもよくなる!という寸法ですね。

正直、上記の2つの関数をマスターするだけでスプレッドシートを使用していく上で十分に快適なデータ管理を行えるでしょう。
なので残り3つはgoogleならではの簡単で便利な関数を紹介します。

3.IMPORTHTML

例えばサイトで画像のような表のデータをスプレに入れたい時どうしますか?

いちいち手入力するのは手間ですよね。しかも頻繁に内容が変わるようなサイトの内容だったら毎回確認して変わってたら書き換えないといけない。

そんなお悩みを解決するのがIMPORTHTMLです。
こちらの関数はHTML内の表やリストをそのままスプレに持ってくることができます。

頻繁に使う機能ではないですが、資料やデータを作る際の時間短縮になると思います

=IMPORTHTML(“URL”,”table or list”,指数)
画像の場合だとURLのHTML内で2つ目のtableを展開しています。

ゲーム会社だと公式HPに載せるスケジュールテーブルとゲーム内の時間がズレないようにこういった関数を使って整合性を取る!なんて形もありかと思います!

4.IMAGE

スプレを他人に共有する際。資料として渡すのであれば画像があると伝わりやすいですよね。
イメージとしてネットで拾った画像を共有することは少なからずあると思います。
そんなとき、一々検索して画像を保存して貼り付けて…って自然にやると思いますが意外とめんどくさかったりします。

そこでこのIMAGE関数。

アピリッツのバナー

URLがあれば画像をスプレに表示させることができます。

=IMAGE(“URL”,モード,高さ,幅)

モードは以下のようにセル依存、アスペクト比依存、サイズ依存、自由のようにサイズを指定できます。

1アスペクト比を変えずに、セル内に収まるように画像サイズを変更します。
2アスペクト比を無視して、セル内に収まるように画像を引き延ばすか決めます。
3画像を元のサイズのままにします。その場合、画像がトリミングされることがあります。
4カスタムサイズに変更することができます。

デザイナーさんなどは自社のサイトに画像を載せた際、そこにリンクしたこの関数を使うといちいち更新しなくて良いので便利かもしれません。

5.GOOGLETRANSLATE

英語のデータやいろんな英文を一気に翻訳したいときにこの関数は役立ちます。
この関数はセルのテキストをGoogle翻訳する関数なのです。

Google翻訳の利点といえばなんと言ってもコスト以上の精度と翻訳言語数にあります。
無料でここまでパッと翻訳できるサービスは他にないでしょう。
もちろん文章が長ければ精度は落ちますが、それでも昔に比べて相当な精度で翻訳を行ってくれます。

画像は単語帳をリスト化した物ですが、こう言った自分なりの単語帳を作る時などにも使えるかもしれませんね。

翻訳する数が膨大な場合はこの関数を使って一覧にすると纏まったデータになるかと思います。

最後に:次回へ続く

いかがでしたでしょうか?スプレを使う上で必須のARRAYFORMULAとIMPORTRANGE、その他3つは作業の効率化に役立つような小技的関数でした。

次回はデータ整理に便利な関数4選を紹介しようと思います。

「ジョブローテーションで人を育てる」エクスペリエンスデザイン部 部長 南 弘紀 インタビュー

0

アピリッツにはゲーム開発の部門が五つあります。そのうちの一つ「エクスペリエンスデザイン部(以下、XD部)」はデザイナーが多く在籍する部署です。部長である南さんに、XD部の特色とどんなチームに育てたいかについて教えてもらいました。(2020年12月 取材)

南 弘紀 (みなみ こうき)
2017年 アピリッツ入社
休日は釣りにいったり海外ドラマや映画を見て過ごす。
海外ドラマはSF(ウエストワールド)からファンタジー(ゲーム・オブ・スローンズ)まで。
映画は恋愛(パンチドランク・ラブ)からアクション(マッドマックス)まで。
釣りはワカサギからシーバスまで。なんでもやります。

ゲーム会社からテレビ局、そして再びゲーム会社へ

ーー 南さんはアピリッツに入社してもうすぐ4年たちます。入社前はどのような仕事をされていましたか?

前職ではテレビ局で映像制作をしていました。それよりも前はちょっと複雑で、最初はコンシューマーゲームの会社でデザイナーとして数年働いたあと、ゲーム開発を目指している会社に縁があって転職しました。が、いろいろあって、そこではゲームが作れなかったんです。それで、テレビ局に入りました。リアルタイムCGとプログラムの知識のある人間が必要ってことだったんです。番組のCG映像を作成したり、バーチャルスタジオの作成をしたり。

ーー ゲーム業界からテレビ業界、そして再びゲーム業界に戻ったのですね。きっかけは何だったのでしょう?

自分がテレビ局で働いていた2014年頃から、スマートフォン向けゲームの会社がテレビ番組の一社提供のスポンサーとして登場しはじめたんです。しかも自分がゲーム業界にいた頃は聞いたことのない社名です。あー勢いがあるんだなと肌で感じました。それで、自分もスマホゲームに関わりたくてアピリッツに入りました。

デザイナーが多いチームでゲーム運営をするメリット

ーー XD部はどういうチームですか?

XD部全体で60人ほど所属しています。このうち50人近くはデザイナーですね。もともとXD部は社外のデザイン制作を受託するデザイン専門の組織でした。今はそれに加えて運営移管を担当し、ゲームの運営チームとしてプランナー、エンジニアも参加してもらっています。

また、去年からアニメ業界出身の人もXD部の仲間に加わりました。アニメをふくめたSDモーションの演出を一貫して作成し、ゲームに取り入れています。世の中の流れを考えても必要な要素です。

ーー ゲームの運営をXD部でやってみていかがですか?

デザイナーが一歩踏み込んだ仕事をできるようになりました。以前の仕事の流れだとプランナーからアートディレクターに依頼があって、その指示に沿って良いものを作りさえすれば良かったのですが、今は自分たちでKPIを分析し改善するところから関われますし、広告も自分たちで考えて提案します。

つまり、誰かと交渉したり、説明する必要ができてきます。「こっちのほうが良いから」だけじゃなく、相手にわかってもらうために「なぜこのデザインが良いのか?」その根拠を提示しながら伝える必要があります。なので、趣味趣向で提案するのではなく、論理的に説明できるデザイナーが育っています。

ーー 南さんはXD部の部長となって半年たちました。どんなチームを育てていきたいですか?

時代に見合った価値のある人材がいる組織にしたいです。

どの業種にしても同じですが、時代に関わらず価値が高く担保される唯一のスキルは「新しいことを学び続ける」スキルだと思います

そのために「ジョブローテーション」を取り入れてます。イラストレーターもモーションもやって、モーションをやってたメンバーをエフェクトチームに入れたり、クライアントエンジニアもサーバー側を触らせたり……。「新しい事を覚えるのが普通」という文化は育てたいですね。

苦労してでも「ジョブローテーション」をやったほうがいい理由

ーー ジョブローテーション、大変ではないですか?

みんな大変ですよ(笑)でも、僕は「やったほうがいい」と判断しています。

まず、向き不向きの問題です。そもそも若い人たちって「アピリッツでこれがやりたい」と入ってくるんです。目的や意欲があることは歓迎しますが、実は「本当に向いていること」への可能性を閉ざしてしまうリスクも生まれます。

なんでもそうでしょ? すべての業種に深みがあります。そしてそれは、やってみないとわからない。

ーー 「意外と向いてた」ってありますよね

はい。山をこえるまではしんどいけど、山をこえた人は新しい武器を手に入れることになるので「やってよかった」ってなるんですよね。

もちろん、知らない仕事に当たってモチベーションが下がることだってあります。しかし「モチベーションが上がらないから新しい事を覚えられない」となってしまうことは相当危険です。環境に左右されず「自分のキャリアのためにも新しいこと覚える」と真摯に取り組める人になってほしい。

ーー  環境に左右されない人は強いし、頼りにされますよね

はい。たとえばデザイナーからアートディレクターを目指す人は多いですが、アートディレクターはゲームの全リソースに責任を持つ仕事です。指示が出せない領域はあってはならないし、ベテランにだってきちんと指示を出さないといけない。

ゲームすべてのデザイン業務の指示が出来て、尖った武器を一つ持っている。そんなアートディレクターが存在したら、プロジェクトにとってこれ以上に頼れる存在はいない。

もちろん、管理側の立場からすると「この人はこれが得意だから」って、つい同じ仕事をアサインしたくなります。そのほうが正直使いやすいしラク。でも、本人にとって本当にいいことなのか? って長い目で考えると、本人のためにはならないと考えています。

だって、これから数年後に現れる若手は義務教育でプログラミングを勉強してるような子たちですよ? ひとつのことしかできない人が本当に今までの価値が担保できるのか? かなり疑わしい。

デザイナー出身の人間として、いまXD部にいる多くのデザイナーに将来のキャリアについてアドバイス出来ることがいろいろあります。そういうとき、僕はただ明るいだけの未来は提示しません。不況の波が一定の間隔で襲ってくることも知っていますし。一つのスキルに特化しすぎて辛酸を舐めている同世代もみています。多才かつ有能な若手だってどんどんあらわれる。

だから生き残れる人になってほしいです。そのためには、今の仕事に向き合い、技術を高め、次のステップに進むことが大切です。

深堀りできるひとは強い

ーー どんな人が伸びていますか? また、どんな人にXD部の仲間となってほしいですか?

ジョブローテであたえられた仕事に知識がない状態で入っても深堀りができる人ですね。勉強して、深堀りして、自分なりの解釈ができる人は伸びています。ときどき「こうあるべき」みたいな形を導き出すひとがいるんです。それって人から教えられてできるものじゃない。

技術や知識は、同業者や他業種の人とかかわることで得た情報を、自分で咀嚼することで、やっと身につけることができます。

今、エンジニアとデザイナーが一緒になってグラフィックデータの軽量化をゴリゴリやっていますが、そういった業務は互いに刺激しあえるので、深堀りができるチャンスだと思うし、両者ともそれをしっかり理解して進めることが出来ています。

何かを極限までやりつめてる人は、他の分野でも深堀りできます。掘りなれてるんでしょうね(笑)なんでもいいんです、研究でもスポーツでも。

ーー 南さん自身も部長になって変わったことはありますか?

経営が見えてきましたし、関わる人が増えて、アピリッツがどういう会社なのかがつかめてきました。契約や経理周りだって自分で勉強しないといけないですし、あたらしい領域を学ぶ訓練をしていなければ出来なかったことだなと思います。

誰しもが認める価値を身につけてほしい

ーー 心がけていることはどんなことでしょう?

なにをおいてもXD部のメンバーの市場価値を下げないこと。社内でも、世の中でも、市場価値が高いことは常に意識しています。デザイン業界には海外勢もいますし、低価格で良い絵を描く人もいっぱいいます。エンジニアリングに関してもプランニングに関しても、今と同じ仕事をしながら今の価値を保つことは難しいと感じています。

そんななかで、企業の中で活躍できる価値の高い人材とは? と考えると、開発や運営の状況をみて動ける人材はプロジェクトにとって有利ですよね。誰しもが認める価値だなと思います。

あとは、若いスタッフに対しては、早い段階で干渉しすぎないことも意識しています。「仕事で悩んでる」とよく聞きますが、業務において「悩む」ことは正しくない。「問題を解決する」ためにどういったアプローチをするか「考える」ことが正しい。そして本人が導き出した「考え」をもとに建設的な会話をおこない、スタッフの成長につなげたいと考えています。

関連記事:アピリッツのその他の役員インタビュー

デザイナーが要件定義に参画するメリット

0

こんにちは。デジタルビジネス部の内田です。
中途入社して1年、Webデザイナーとして様々なプロジェクトに関わって制作を行ってきましたが、最近では制作の前段階となる要件定義フェーズに加わることが増えてきました。

ディレクターやコンサルタントなどが担うことも多い要件定義フェーズですが、デザイナーがもっとビジネス的視点を持ってプロジェクトに関わることで、プロジェクトにもデザイナー自身にもメリットがたくさんあることを実感しました。
そこで、この記事ではデザイナーが要件定義に加わることで、どのようなメリットがあるのかをご紹介していきます!

そもそも要件定義とは?

Webサイトの制作やリニューアルを行う際、いきなり制作に入るのではなく、課題の整理やゴールの設定、現状や競合他社の分析・調査を行いつつ、ページの設計や構想をはっきりと定めます。

制作前にこのフェーズで構想を固めることで、のちの工程では決定した設計に沿ってフロント制作・システム開発に集中できたり、致命的な設計漏れなどを防いだりすることができます。

メリットその1:クライアントのビジネス課題を直接ヒアリングできる

メリットその1は、直接クライアントと会えるということです!
通常、Webデザイナーはユーザー視点に立ってデザインしがちな面があると思います。
また、クライアント視点の要件といったものはいくつか伝えられる程度で、顧客と会うことがあってもWeb担当者くらい…ということも少なくありません。

しかし、要件定義の段階だと、社長や取締役、営業担当者、実店舗のあるクライアントであれば実際にお客さんと会い、現場の実情をよく理解している人などなど…様々な方と会う機会があります。会議の場だけではなく、雑談や呟き程度でもその業界やクライアントの課題・目指したい方向性をより深く理解することができます。

このようにクライアントのニーズを直接伺って把握しておくことは、実際にプロジェクトの進行をスムーズにするだけでなく、デザイナーとしても制作の方向性が明確になったり思考の引き出しが増えたりするため大きなメリットになると実感しています。

メリットその2:定量的なデータを根拠に設計ができる

要件定義フェースでデータをもとにサイトの現状分析や問題提起、改善案の提示を行うことは、より効果的なサイト改善や制作に繋がります。私は部内のマーケティンググループに所属しているため、日頃からアナリストやコンサルタントの業務内容を聞いたり、アドバイスしあったりすることができます。そんな環境の助けもあって、クライアントにも「数字による根拠のある画面設計」を行えることはとても大きな強みだと思っています。

例えば、目的の売り上げやコンバージョン率を達成するために現状のデータを分析して、「このページでは◯%のユーザが離脱してボトルネックになっています!改善しましょう!」「そうですね!」とクライアントと示し合わせることで、なぜこの部分を改善する必要があるのかという明確な理由と双方の合意を経た制作を進めることができます。

また、デザイン制作段階でも、カラーや雰囲気はどういった感じにしたいかという要望だけでなく、「このページでは◯%のユーザが離脱しているからボタンのクリック率を◯%から◯%に上げたい」という課題が明確になっていることで、よりビジネス課題を解決できるデザインを提案することが可能になります。

メリットその3:制作経験があるからこそトラブルを防げる

プロジェクトの制作工程のみを担当している際、「この予算とスケジュールでは実装できないのですが…」「これはどう実装すれば…?」「この改修をしたいならエンジニアさんのアサインが必要だ!」と困った事態に陥ることがあります。

要件定義時に実現可能性が曖昧だと(これが起こるのは曖昧かどうかも判断できていない場合が多いですが)あとあと困ったことになるので、制作経験があるとこの辺りの判断が素早くできるのも強みだと思います。

まとめ

これまでのメリットをまとめると、実は自分が制作するときに揃えたいものを整理しているだけでは…?という気もしてきますが、デザイナーの視点と経験を要件定義に生かすことはクライアントや社内のメンバーなど、関わる人全てが障害なく役割に尽力して目的達成に近づく大きな手助けになると考えています!

【祝! 日本一】第12期 女流球聖位 荒木 愛 インタビュー【ビリヤードと仕事の話をします!】

0

エンパワーメントサービス部の荒木さんが日本アマチュアポケットビリヤード連盟主催の「第12期 女流球聖戦」を制し、タイトルを獲得しました! 日本一のポケットビリヤード選手がアピリッツにいる……! ということで、優勝記念インタビューです!

毎日ビリヤードの練習してます

―― まずは、アマチュアポケットビリヤード日本一、おめでとうございます!

ありがとうございます。

―― 荒木さんは毎日オフィスにいますよね。ビリヤードの練習は、いつ、どうやって……?

実は、ほぼ毎日やってます。仕事終わりにオフィスから歩いてすぐのところにある「ビリヤード相馬」というビリヤード場に通っているんです。原宿の駅前の老舗ビリヤード場です。私がアピリッツに入ったきっかけのひとつも「オフィスの立地が良いから(ビリヤード的に)」というものだったりしますし。練習方法は一人でやるよりも、お店の常連さんと一緒にプレイすることが多いです。

ただ、今年の4月頃は新型コロナウイルス感染症の影響でお店も閉まっていました。家で練習できる競技でもないので苦労しましたね。

―― そんななか優勝! ビリヤード歴はどのくらいですか?

13年です。ここまで大きな大会で勝ったのは今回が初めてでした。

JPA企業対抗戦に出たい

―― 「荒木さんはビリヤード強いよ」と噂には聞いていましたが、そんなにお強いとは

はい(笑) アピリッツ社内にもビリヤード部があります。 部員募集中です。初心者大歓迎ですし、私が教えます!

いつかアピリッツのみんなで”JPA企業対抗戦”に出てみたいんです。強い人ばかりのチームだと参加できないルールで、上級者、中級者、初級者の3人で一緒に頑張ります。(※ 現在はCOVID-19の対策のためビリヤード部はお休み中です)

―― 荒木さんと、あと2人で「チームアピリッツ」ということですね

はい。「武蔵野市役所」さんとかすごくお強いんですよ。企業対抗戦でも勝ちたい。

―― あの、その机の横にある黒い物体は……?

「キュー」です! 今日このあとビリヤード場に持っていきます!

机にたてかけてお仕事中。ビリヤードの試合では袖がひらひらした服装だとプレイできないので、シャープな服装の人が多いそうです。

―― ちょっとだけ見せてください!

職人さんに作ってもらったカスタムキューだそうです
「ゴエティアクロス」のワッペン。このポケットには「チョーク」も入ってます

クリエイターと並走する仕事

―― ずっとビリヤードの話を聞いていたいんですが、お仕事のことも知りたいです。エンパワーメントサービス部で荒木さんはどんな役割を担っていますか?

社外のプロジェクトで働いているアピリッツ社員のサポートです。契約周りや事務的なことはもちろん、1 on 1 の打ち合わせを重ねて、その人の仕事内容や、問題点をヒアリングして、一緒に考えていく役目です。

アドバイスというより一緒に考えて並走する役割です。「あなたは、どうしたい?」「こういう切り口はどう?」って。場合によっては、私が本人に変わってプロジェクトのご担当者さまと話し合うこともあります。

―― ES部のメンバーに「アピリッツの一員」と実感してもらうために大切なことは何でしょう?

そこはいつも気にかかっています。まずは「安心して働ける環境をつくる」ことを心がけています。誰だって最初は「外部のプロジェクトに一人で参加する」って不安なことです。なので、心細さが和らぐように連絡や面談は丁寧に重ねますし、外部との面談にも同席します。そして「本人の意志を尊重」して動いています。

ただ、みなさん不安なのは最初だけですね。やがてプロジェクト内で評価されて自信をつけていきます。

また、大抵の場合は大手ゲーム会社さまのプロジェクトです。外部スタッフを受け入れることに慣れている会社さまが多いので、そういった意味でもスムーズに進みます。誰もが知っているIPを取り扱ったり、大規模プロジェクトに参加できたり。そういった意味でも面白いはずです。(あと社員食堂が美味しかったり……)

ゲーム業界で働きたいクリエイターの方はぜひ「アピリッツクリエイターズ」をチェックしてください!

―― 外部の会社さまからアピリッツの社員の評価はいかがですか?

評価は高いですよ! みなさんアピリッツの正社員で、熱心なクリエイターで、とても真面目なので。

―― 会社で働いて、社外でもひたすらビリヤードで戦って……両立ってできるものなのですね

できますできます。ちなみにビリヤード界は老若男女いらっしゃいますし、職業もバラバラです。エンジニアさんも多いので、みなさんぜひアピリッツに来てほしいですね。ビリヤード場も近いですし(笑)

女性でもひょいっと背負えるサイズ

―― さいごに、今後の目標を教えて下さい

ビリヤードは「今回はラッキーだった」と思われないように、そしてアピリッツではみんなが仕事しやすいように立ち回りたいです。

―― ありがとうございました!

未経験でIT業界への転職ってどんな感じ? DMM WEBCAMP(DMM ウェブキャンプ)出身のエンジニアに本音で語ってもらいました

0

IT業界未経験からプログラミングスクールを経てアピリッツに転職したみなさんにお話を聞くと、みなさん覚悟を持って異業種から挑戦しているのだなと感じます。今回はDMM WEBCAMP 出身の3人のエンジニアに、学習や転職活動のこと、新型コロナウイルス感染症の影響がどんなものであったか、そしてアピリッツに入ってからの様子を教えてもらいました。

【お知らせ】プログラミングスクール出身者のエンジニア積極採用キャンペーン実施中!

―― IT業界を志したキッカケを教えてください

ただ、日本を長期間はなれて働くことが徐々に自分の人生と合わなくなって退職しました。少し空白期間を置いたのち、「技術を高めていく仕事がしたい」と思ってIT業界を志しました。もともと興味がありましたし、年齢も20代後半だったので、キャリアチェンジのラストチャンスを逃して後悔をしたくないという思いもありました。

新奥:私はもともと海運会社で航海士を5年やっていました。「人が経験していないことを経験したい!」と思ったからです。実際、言語も文化もちがうクルー達と大海原を航海した5年間は今の私をかたちづくる人生の糧となっています。

柴田:私は「ものづくり」により深く関わりたかったからです。前職は広告代理店に勤めていました。そこでWebサイトの文章作成に関わったときに達成感があって楽しかったので、エンジニアを志しました。多くの人に使ってもらえるサービスをイチから作りたいです。

角:学生時代からパソコンを触るのが好きでしたが、深く学ぶチャンスがなくてIT業界とは縁遠いなあと思っていました。でも、プログラミングスクールの存在を知って、一度挑戦してみることにしたんです。愛知から引っ越してスクールに通いました。……そうこうしているうちに、コロナの波がやってきて。

―― ちょうどみなさんがスクールに通っていた頃に、新型コロナウイルス感染症拡大の問題が大きく取り上げられるようになりました。やはり影響は大きかったのですね

角:とにかく就職活動がどうなるのか本当に不安でした。愛知からはるばる引っ越してきたのに、タイミングを間違えたかも? って。ただ、仲間がいたので励みになりました。今でも一緒に勉強したり、飲みに行きます。

新奥:私も仲間の存在は大きかったですね。本当ならDMM WEBCAMPのおしゃれな教室で勉強するはずだったのに、コロナ禍の影響で完全在宅で学習することになったんです。幸い、オンライン授業の体制がすぐに整いましたし、仲間ともオンラインでめちゃくちゃ密にコミュニケーションをとりました。

柴田:チーム開発はやっぱり楽しかったですよね。達成感がありました。不安はみんな抱えていましたよ。求人数も減っていくなかで、未経験エンジニアが本当に転職できるのか? って。でも周りのみんなも真剣に頑張っていましたし、お互い励まし合いました。

ES部 角さん

―― 未経験からエンジニアになるための勉強は、だいたいみなさん「毎日8時間くらい」とおっしゃいます

柴田:そうですね。一週間のうち一日は休息・自由日にして、それ以外の日は平均して一日に8時間は勉強していました。期間は、スクールに入って、アピリッツに入社するまでの8ヶ月です。

角:僕も8時間。ただ、スクールに入るまではどんな勉強をしたらいいのか謎で「やる気が出たら一時間やる」……といった感じでした。スクールに入ってからはコツや目処がついたので、勉強が楽しくなりました。期間は4ヶ月くらいです。

新奥:勉強だけに打ち込む環境を作ったあとは、毎日8時間、ほぼ休みなく続けていました。そんな生活を半年ほど続けていたので、アピリッツに入社を決めてから3日間はYou Tubeとか見ながらひたすらダラダラしました。

―― 就職活動はいかがでしたか?

柴田:とある企業さまから「あなたを採用したら企業にどんな利益がありますか?」とズバッと尋ねられて、その場できちんと答えられず悔しかったです。ただ、あらためて自問自答する良いキッカケをいただいたと思います。

新奥:最初に面接を受けた会社で内定をいただけたんです。採用の連絡をもらったときは家で一人で叫びました。ああ自分の頑張りが認められたんだ、って。アピリッツの面接では将来のビジョンを深堀りされて、5年、10年後のキャリア像をきかれるのはもちろん、「20年・30年後はどうなっていたい?」なんて部長から訊かれたり。びっくりしましたね。

角:面接では「嘘はやめよう」と真摯にのぞみました。

――アピリッツに決めた理由を教えて下さい

角:今まで習ってきたRuby on Rails、AWSといった内容を手広くやっている印象だったのと、会社と一緒に自分も成長できると感じたからです。

ES部 柴田さん

柴田:あと、技術力や情報発信力の高さも魅力でしたね。面接での話しやすさも大きかったです。私の色んな面を掘り下げてもらえましたし、キャリア展望のこともふくめ、腹を割って本音で話せました。

新奥:専門性の高いエンジニアがいるのは魅力的でした。自社のエンジニアの成長を重視している会社だとも感じました。ここなら、キャリアの幅が広がりそうだなと考えました。

―― 実際に働き始めていかがですか? 今までとのギャップはありましたか?

角:デスクワークってこんなに体が疲れないんだなと驚きました。仕事は、先輩のフォローがあるのでなんとかやっていけているなと思います。エンジニアって優しい人が多いなと……。

新奥:そうですね、実際に入ると、いろいろ安心しました。エンジニアYouTuberの動画を見ていると「モダンな技術を扱えないと未経験からのエンジニア就職は無理、入社してもすぐ落ちこぼれてクビになります!」ってめっちゃくちゃ煽られるんですけど、そんなことなかったなって思いました。もちろん勉強は必要ですし、年下や同い年のエンジニアが私の先輩です。日々食らいつくように働いています。

あと、業務指示への返答は「Yes, Sir!」が基本だった元船乗りの立場からすると、Slackのやりとりにびっくりしますね。上司にスタンプ一個で返事したり。ラフで良いなあと思いますね。

柴田:未経験でもすぐに開発現場に入れる環境があったので良かったです。あと定時退社の方も少なくないですし、ホワイトだなと思います。経験を積んで、将来はプロジェクトマネージャーやリーダー的存在になりたいです。そして多くのひとに使ってもらえるサービスを作りたいですね。

―― 最後に、スクール生のみなさんにメッセージをお願いします

柴田:勉強でも、転職でも、すぐに結果が出ないこともあるはずです。でも自暴自棄になったりせず、気持ちを整理しながら根気強く頑張ってほしいです。リフレッシュも大切ですよ!

新奥:未経験からエンジニアを目指すと、いろんな情報に出合って混乱するかもしれません。「コロナで未経験からのエンジニア就職は無理!25歳以上は諦めろ」とか、反対に「未経験からのエンジニア就職はこれさえ抑えれば楽勝」という有料NOTEが売ってたり。そんなカオスに惑わされず、一歩一歩確実に進んでほしいです。

私も、日々の業務に全力で取り組んで「スタートが遅くともそこからの努力次第で十分に活躍できる」ということを自身のエンジニア人生をかけて証明していきたいです。

MS部 新奥さん

角:やめないかぎりは誰でもできるようになるはずです。ですから、周りばかり気にせず、カオスな情報にまどわされず、自分のペースでがんばってください。僕もいつかはできるようになると自分を信じてがんばります。

動的サイト向けのテンプレートを作成する時に押さえておきたいポイント

0

デジタルビジネス部所属Webデザイナーの今井です。
動的サイトのデザインというのは静的サイトに比べると変化が多く、その分考慮すべきことがたくさんあります。
今回はWebディレクターやデザイナー向けに手戻りの少ないテンプレートを作成するポイントをご紹介します。

文字数の増減による変化

商品名やニュース記事のタイトルなど、文字数が一定ではない情報は動的サイトには数多く存在します。
ECサイトの一覧では画像の下にタイトルと金額が、ニュースサイトでは画像の下に記事タイトルや日付等が入るのはよくあるパターンですが、このタイトルがすべて同じテキストであるというのもワイヤーフレームやデザインではよくあるパターンです。
しかし実際にはタイトルはデザインの想定通りにはまらないことも少なくありません。
タイトルを2行で想定したデザインの場合、タイトルが1行分しかなかったらその下の要素は上につまる?それとも位置は変わらない?
デザインにあるより長いタイトルもそのまま全部表示する?それとも2行を超える場合は「…」と省略する?
タイトルの表示方法についてはシステムの仕様はあまり深く関わらないため組み込みで戻ってくることは少ないです。
しかし見栄えに関わるため、実態に近い状態を想定してUIを考慮して決めておくことで実装後の修正を防ぐことができます。

要素の増減による変化

文字数の長短以外にも、要素そのものが増えたり減ったりすることもよくあるケースです。
閲覧したアイテムを他のページで一覧表示する場合、1列5件まで表示できるとして、6件以上あったらどうなるのか。
最大5件までしか表示しない?それとも2列目もある?あるいはスライダーが起動する?
これはシステム要件とも関わるので、事前に確認しておきたいポイントです。

バリエーションの網羅性

ECサイトの場合他にもよくある変化として、購入可能、完売、予約、再入荷待ちなどのステータスがあげられます。
また、新着やおすすめなどのタグデータを持つものもあるし、セール価格を表示することもあります。
ワイヤーフレームでは考えられるすべてのパターンを網羅し、必要なだけデザインのバリエーションを作成しておくことで、コーディング時に必要なパーツを網羅することができ、組み込み時のパーツ不足による手戻りを防ぐことができます。

データの表示方法

動的サイトでは多くの項目がデータベースの値を出力することで表示されています。
ここで気をつけたいのは、データベースから出力されるデータにはタグを挿入できない、ということです(元々のデータにタグが入っている場合は別ですが)。
例えば商品名や記事タイトルのような要素はデータベースでは1つのデータとして格納されていて、テキストの一部だけ太字にしたくてもできないし、読みやすいように途中に改行を入れることもできません。
日時表示をする際に、日付と時間が1つのデータとして扱われていたら、時間だけ小さく表示する、ということはできません。しかし、日付と時間がそれぞれ別のデータとして存在していたら、時間だけ小さく表示することができます。
データベースにどのようにデータが格納されているかはデザインに落とし込む際に大事なポイントです。

ボタンクリックによる挙動

Webページには多くのボタンやリンクが存在します。
クリックして遷移する、フォームが送信される、jsによるインタラクションが発生するというのが予想される挙動ですが、動的サイトのコーディングをする場合ページ遷移を実装するかどうかは場合によるため、基本的に実装しておくべき挙動がある場合はコーダーに挙動に関する情報を共有しましょう。
特にモーダルやtoggleのような要素は、テンプレートをコーディングするコーダーが起動するところまで実装するのか、システムに組み込む際にエンジニアが実装するのか線引きが曖昧な部分があるため、コーディング時に何を実装すべきかは組み込むを行う開発者と協議して明確にしておいた方がよいでしょう。

toggleする要素の変化

メニューボタンをクリックすると折り畳まれていたメニューがtoggle展開する。よくある仕組みです。
また、最初の数行だけ表示して「もっと見る」を押すと残りがtoggle展開で表示されるというケースもよくあります。
一度展開した要素を再び閉じることができるのか、閉じることができるなら「もっと見る」のテキストが「閉じる」に変化するのか。
よくあるがゆえに「普通こうなるだろう」という思い込みで挙動に関する情報が足りないことがあります。
「もっと見る」は「閉じる」に変わるのが普通かもしれないし、「もっと見る」を開いた後は閉じられなくなるのが普通かもしれません。
当たり前の挙動をする場合もコメントやデザインで明示しておくことで、当たり前を共有することができます。

モーダルの挙動

メッセージや拡大画像、情報を表示する際によく使われるモーダル。
情報やフォームを表示する場合、モーダルで表示されるコンテンツがブラウザの高さにおさまらない場合、ブラウザ全体がスクロールするのか、モーダル内でスクロールするのかというのがまず大きなポイントです。
モーダル内でスクロールする場合、見出しや下部にあるボタンは固定されるのか、固定される場合、それぞれどの程度の領域が必要になるのかをデザインの段階までに決めておかないと、コーディング時に思ったより固定される領域が大きくてコンテンツが見づらい、ということが起こります。
また、モーダルは基本的に閉じる手段が必要です。
×ボタンや閉じるボタンが設置されているか、すべてのモーダルで同じ位置にあるか、あるいはモーダル内から別ページに遷移させるために閉じられないようにするのかを、システムの仕様も踏まえて決めておく必要があります。
画面全体を半透明のオーバーレイで覆っている場合、オーバーレイをクリックして閉じるかどうかも必要な情報です。

0件/エラーパターン

一覧で0件だった場合、フォームの入力エラーなどは必要ながらもつい忘れられがちな要素です。
特にフォームのエラーはシステム的に出力されるので、デザインを作成する際にはすべてのフォームで統一されたデザインにしておく必要があります。
フォームが存在するすべての画面にエラーデザインを作ることは時間もコストもかかりすぎるため、通常はピックアップされた2〜3画面にエラーパターンを追加する程度になりますが、フォームはエラーがでることを念頭にデザインを作成すると良いでしょう。

最後に

動的サイトで変化するポイントは他にもいろいろありますが、これまで私が経験した多くのWebサイトに当てはまるポイントをご紹介しました。
どこがどう変化するか、というのは想像力も必要です。上記のポイントを踏まえて、自分が作成しようとしているワイヤーフレームやデザインが実際に動くとどうなるかを想像してみてください。今のワイヤーフレームやデザインでは足りないパーツや、必要なパターンが見えてくるかもしれません。

機械学習によるアイコン画像生成のこころみ (実践編)

0

実践編では、機械学習の手法によるアイコン画像の生成について書いていきます。

前回の下調べ編では CycleGAN でのスタイル変換によるアイコン画像生成の先例を見ていきました。今回はその再現を実践していきます。

実践にあたっては以下を順に見ていきます。

  1. 実装
  2. データセット
  3. 実行環境

1.実装

実装は前述のとおり junyanz/pytorch-CycleGAN-and-pix2pix を利用したとのことなのでこれを利用します。データセットを所定のディレクトリに配置し学習します。

おそらく以下のような実行方法になります。

# 32x32 のデータセットを配置し、そのデータセットでの学習 (4つの GPU があるものとする)
python train.py --dataroot ./datasets/iconify32x32 --name iconify_cyclegan --model cycle_gan --gpu_ids 0,1,2,3 --batch_size 16
# 64x64 のデータセットでのファインチューニング
python train.py --dataroot ./datasets/iconify64x64 --name iconify_cyclegan --model cycle_gan --gpu_ids 0,1,2,3 --batch_size 16 --continue_train
# 128x128
python train.py --dataroot ./datasets/iconify128x128 --name iconify_cyclegan --model cycle_gan --gpu_ids 0,1,2,3 --batch_size 16 --continue_train
# 256x256
python train.py --dataroot ./datasets/iconify256x256 --name iconify_cyclegan --model cycle_gan --gpu_ids 0,1,2,3 --batch_size 16 --continue_train

まず最初に解像度の低い画像のデータセットで学習し、だんだん解像度を上げていきます。この実装では --continue_train フラグを指定することで、モデルをファインチューニングできるので、2回目以降の解像度ではファインチューニングとして実行していきます。

2.データセット

ロゴ画像については、400×400 のサイズの画像をリサイズしていけばよさそうです。一方で実写の物体の画像を用意するのはひと手間かかる予感がします。

pycocotools を使って COCO のアノテーション情報をもとに加工していきます。ひとまずどんなライブラリかコンソールで確認していきます。

>>> from pycocotools.coco import COCO
>>>
>>> annotation_path = 'datasets/coco/annotations/instances_train2017.json'
>>> coco = COCO(annotation_path)
loading annotations into memory...
Done (t=23.60s)
creating index...
index created!

画像のリソースや、そのアノテーション情報にアクセスできます。

>>> img_id = coco.getImgIds()[0]
>>> img_id
391895
>>> img = coco.loadImgs(img_id)
>>> img
[{'license': 3, 'file_name': '000000391895.jpg', 'coco_url': 'http://images.cocodataset.org/train2017/000000391895.jpg', 'height': 360, 'width': 640, 'date_captured': '2013-11-14 11:18:45', 'flickr_url': 'http://farm9.staticflickr.com/8186/8119368305_4e622c8349_z.jpg', 'id': 391895}]

画像のリソースの情報にアクセスできます。

なお、ここでの license の項目は画像のライセンスをあらわす定数のようです。完全に脱線してしまいますが、アノテーションファイルの JSON から jq .licenses instances_train2017.json などとしてライセンスの情報をみてみます。

[
  {
    "url": "http://creativecommons.org/licenses/by-nc-sa/2.0/",
    "id": 1,
    "name": "Attribution-NonCommercial-ShareAlike License"
  },
  {
    "url": "http://creativecommons.org/licenses/by-nc/2.0/",
    "id": 2,
    "name": "Attribution-NonCommercial License"
  },
  {
    "url": "http://creativecommons.org/licenses/by-nc-nd/2.0/",
    "id": 3,
    "name": "Attribution-NonCommercial-NoDerivs License"
  },
  {
    "url": "http://creativecommons.org/licenses/by/2.0/",
    "id": 4,
    "name": "Attribution License"
  },
  {
    "url": "http://creativecommons.org/licenses/by-sa/2.0/",
    "id": 5,
    "name": "Attribution-ShareAlike License"
  },
  {
    "url": "http://creativecommons.org/licenses/by-nd/2.0/",
    "id": 6,
    "name": "Attribution-NoDerivs License"
  },
  {
    "url": "http://flickr.com/commons/usage/",
    "id": 7,
    "name": "No known copyright restrictions"
  },
  {
    "url": "http://www.usa.gov/copyright.shtml",
    "id": 8,
    "name": "United States Government Work"
  }
]

上記の画像のリソースの情報は CC BY-NC-ND なので、会社のブログで画像を切ったり貼ったりするのには適さなそうです。CC BY 2.0 の 4 からランダムに選んでみます。

>>> ids = coco.getImgIds()
>>> imgs = coco.loadImgs(ids)
>>> import random
>>> img = random.choice([i for i in imgs if i['license'] == 4])
>>> img
{'license': 4, 'file_name': '000000226571.jpg', 'coco_url': 'http://images.cocodataset.org/train2017/000000226571.jpg', 'height': 426, 'width': 640, 'date_captured': '2013-11-18 21:53:31', 'flickr_url': 'http://farm4.staticflickr.com/3037/3054252115_dca3690eb8_z.jpg', 'id': 226571}
000000226571.jpg

4 of 4 Two Equestrian Horse Riders on Morro Strand State B… | Flickr

馬にのった人物の画像でした。

補足:一応クレジット表示のためにもとの画像の URL もさがしておきます。Find photo URL by filename of jpg によるとファイル名から探せるようなのでさがします。今回は http://flickr.com/photo.gne?id=3054252115 → https://www.flickr.com/photos/mikebaird/3054252115/ で探せました。以上脱線終わりです。

つづいてアノテーションも見てみます。

>>> ann_ids = coco.getAnnIds(imgIds=[img['id']])
>>> ann_ids
[54013, 54104, 185138, 209986, 1376036]
>>> anns = coco.loadAnns(ann_ids)
>>> ann = anns[2]
>>> ann
{'segmentation': [[345.95, 149.26, 345.95, 152.32, 345.95, 155.0, 340.98, 156.91, 330.65, 163.03, 332.18, 164.57, 339.06, 165.33, 334.47, 176.43, 326.82, 187.52, 325.29, 193.64, 326.44, 208.18, 325.29, 223.86, 325.29, 237.64, 342.12, 263.27, 352.07, 272.02, 352.84, 294.97, 359.72, 322.52, 359.72, 332.08, 364.69, 329.79, 365.08, 326.34, 368.14, 314.1, 371.58, 314.48, 372.73, 321.75, 373.88, 327.87, 375.02, 330.93, 382.29, 329.79, 383.06, 329.4, 383.44, 329.4, 384.97, 325.2, 381.91, 324.81, 375.79, 319.07, 373.11, 312.95, 370.43, 303.39, 370.05, 299.18, 370.43, 289.62, 370.43, 267.04, 364.31, 253.27, 358.96, 238.02, 364.31, 233.43, 363.93, 222.72, 371.58, 221.19, 384.59, 220.8, 390.71, 220.04, 389.18, 216.21, 387.65, 212.39, 386.5, 210.09, 376.94, 211.62, 363.93, 212.39, 362.4, 192.88, 366.99, 182.21, 364.31, 182.21, 360.49, 181.83, 356.66, 179.92, 356.66, 178.77, 361.25, 178.77, 362.78, 175.33, 363.55, 173.03, 366.23, 172.65, 367.37, 171.5, 366.61, 166.91, 367.37, 163.47, 368.14, 161.94, 375.02, 163.09, 381.15, 163.09, 380.38, 160.41, 367.76, 155.05, 365.08, 146.25, 352.84, 145.11, 344.42, 147.4]], 'area': 5287.617649999996, 'iscrowd': 0, 'image_id': 226571, 'bbox': [325.29, 145.11, 65.42, 186.97], 'category_id': 1, 'id': 185138}

これだけだとよくわからないのでマスクに変換して形状を見てみます。

>>> mask = coco.annToMask(ann)
>>> mask
array([[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, 0, 0],
       [0, 0, 0, ..., 0, 0, 0]], dtype=uint8)
>>> import numpy as np
>>> from PIL import Image
>>> masking = Image.fromarray(mask * 255) # mask は 0, 1 の numpy.ndarray になっているので 1 の部分を白くするために 255 をブロードキャストします
>>> masking.save('masking.jpg')
masking

このアノテーションは上の画像の人間の部分のようです。

これをつかって切り抜いてみます。

>>> from skimage import io
>>> image = io.imread(img['coco_url'])
>>> image[np.where(mask == 0)] = 255 # マスクで 0 になっている部分 (背景部分) を白くしてしまう
>>> Image.fromarray(image).save('masked-image.jpg')
masked-image

対象領域だけにしぼってみます。すこし煩雑になってきたのでメソッドを定義します。

>>> def object_rect_indices(mask):
...     '''アノテーションのマスクからオブジェクトの矩形領域の両端 (top, bottom, left, right) を返す
...     '''
...     ys, xs, *_ = np.where(mask == 1) # mask は2次元配列の想定
...     top = ys.min()
...     bottom = ys.max()
...     left = xs.min()
...     right = xs.max()
...     return (top, bottom, left, right)
...
>>> def clip_image_margin(image, mask):
...     '''画像の余白を削って返す
...     '''
...     top, bottom, left, right = object_rect_indices(mask)
...     return image[top:bottom, left:right]
...
>>> clipped = clip_image_margin(image, mask)
>>> Image.fromarray(clipped).save('clipped.jpg')
clipped

よさそうです。正方形にしてしまいます。

>>> def to_square(image):
...     '''画像の ndarray を、長辺にあわせて正方形に余白を追加した ndarray を返す
...     '''
...     h, w, *_ = image.shape
...     pad_width = [(0, 0)] * image.ndim # 2値画像なら二次元分、RGB 画像なら三次元分
...     if h > w:
...         # 縦長なので横方向にパディングする
...         size = h
...         padding = size - w
...         before = padding // 2
...         after = padding - before
...         pad_width[1] = (before, after)
...     else:
...         # 横長なので縦方向にパディングする
...         size = w
...         padding = size - h
...         before = padding // 2
...         after = padding - before
...         pad_width[0] = (before, after)
...     padded = np.pad(image, pad_width, constant_values=255) # 余白は白で埋める
...     return padded
...
>>> square_image = to_square(clipped)
>>> Image.fromarray(square_image).save('square-image.jpg')
square-image

こういう画像が用意できたらあとはリサイズしていけばよさそうです。


今回は以下のようなスクリプトにまとめて小さい画像を排除しつつ切り出しとリサイズを行いました。

import numpy as np
from PIL import Image
from pathlib import Path
from pycocotools.coco import COCO

# instances_train2017.json でのアノテーションでは、セグメントのピクセルサイズの
# 中央値が 1696 くらいなので、ひとまず 1500px あれば小さいとはみなさないことにする。
SMALL_IMAGE_PIXEL_THRESHOLD = 1500

# データセット用にリサイズするサイズ
SIZE_32x32 = (32, 32)
SIZE_64x64 = (64, 64)
SIZE_128x128 = (128, 128)
SIZE_256x256 = (256, 256)

def is_satisfied_object_size(mask, min_threshold=SMALL_IMAGE_PIXEL_THRESHOLD):
    '''アノテーションのマスクの ndarray から対象セグメントのサイズが訓練に使えるサイズかどうかを判断して返す
    '''
    return np.size(mask[mask == 1]) >= min_threshold

def extract_object(image, mask):
    '''マスク対象の画像 image の ndarray と、mask の ndarray で、対象のセグメント部分以外を白く塗り潰した ndarray を返す
    '''
    extracted = image.copy()
    extracted[np.where(mask == 0)] = 255 # セグメントのオブジェクト以外の部分を白くする
    return extracted

def object_rect_indices(mask):
    '''アノテーションのマスクからオブジェクトの矩形領域の両端 (top, bottom, left, right) を返す
    '''
    ys, xs, *_ = np.where(mask == 1) # mask は2次元配列の想定
    top = ys.min()
    bottom = ys.max()
    left = xs.min()
    right = xs.max()
    return (top, bottom, left, right)

def clip_image_margin(image, mask):
    '''画像の余白を削って返す
    '''
    top, bottom, left, right = object_rect_indices(mask)
    return image[top:bottom, left:right]

def to_square(image):
    '''画像の ndarray を、長辺にあわせて正方形に余白を追加した ndarray を返す
    '''
    h, w, *_ = image.shape
    pad_width = [(0, 0)] * image.ndim # 2値画像なら二次元分、RGB 画像なら三次元分
    if h > w:
        # 縦長なので横方向にパディングする
        size = h
        padding = size - w
        before = padding // 2
        after = padding - before
        pad_width[1] = (before, after)
    else:
        # 横長なので縦方向にパディングする
        size = w
        padding = size - h
        before = padding // 2
        after = padding - before
        pad_width[0] = (before, after)
    padded = np.pad(image, pad_width, constant_values=255) # 余白は白で埋める
    return padded

def extract_square_object_image(image, mask):
    '''正方形にセグメント対象を切り抜いた ndarray を返す
    '''
    extracted = extract_object(image, mask)
    clipped = clip_image_margin(extracted, mask)
    square_image = to_square(clipped)
    return square_image

def image_file_name_from_annotation(ann):
    '''アノテーションから画像ファイル名を返す
    '''
    return '%012d.jpg' % ann['image_id']

def load_image(ann, image_src_dir_path):
    '''アノテーションからアノテーション対象のオリジナル画像を返す
    '''
    # image は image_src_dir_path にアノテーション対象の画像があるのものとして読み込む (なければそのまま例外スロー)
    file_name = image_file_name_from_annotation(ann)
    src = Path(image_src_dir_path) / file_name
    image = np.array(Image.open(str(src)))
    return image

def make_datasets():
    '''写真画像のデータセットをつくる

    対象のみを切り出し白背景にして、32x32, 64x64, 128x128, 256x256 のサイズにリサイズした画像を作る。

    datasets/coco/annotations/instances_train2017.json のアノテーション情報と画像をもとに、以下のサイズごとのディレクリにリサイズして画像を置く

    - datasets/images/photo/32x32
    - datasets/images/photo/64x64
    - datasets/images/photo/128x128
    - datasets/images/photo/256x256

    各サイズごとに 447921 とか画像が作られるので時間がかかる (適当なところで break したほうがいいかも)
    '''

    # photo_image.py
    current_file_path = Path(__file__).resolve()

    # coco の情報
    coco_base_path = current_file_path.parent.joinpath('datasets/coco')
    coco_annotation_path = coco_base_path / 'annotations/instances_train2017.json'
    coco_image_path = coco_base_path / 'train2017'

    # 出力先
    image_datasets_path = current_file_path.parent.joinpath('datasets/images')
    image_datasets_path.mkdir(parents=True, exist_ok=True)

    # 写真画像の出力先
    photo_image_dataset_base_path = image_datasets_path / 'photo'
    photo_image_dataset_base_path.mkdir(parents=True, exist_ok=True)

    # 4サイズつくる
    sizes = [SIZE_32x32, SIZE_64x64, SIZE_128x128, SIZE_256x256]
    dests = ['32x32', '64x64', '128x128', '256x256']
    # ディレクトリ掘っておく
    for directory in dests:
        path = photo_image_dataset_base_path / directory
        path.mkdir(parents=True, exist_ok=True)

    size_with_dst_pairs = list(zip(sizes, dests))

    # coco のアノテーションと画像ファイルからリサイズしたデータセット画像作成
    coco = COCO(str(coco_annotation_path))
    ann_ids = coco.getAnnIds()
    for ann in coco.loadAnns(ann_ids):
        ann_id = ann['id']
        print(f'process {ann_id}')
        mask = coco.annToMask(ann)
        if not is_satisfied_object_size(mask):
            # サイズが小さければスキップ
            print('skipped.')
            continue
        image = load_image(ann, coco_image_path)
        square_image = extract_square_object_image(image, mask)
        object_image_file_name = f'{ann_id}.jpg'
        for size, dirname in size_with_dst_pairs:
            dest = photo_image_dataset_base_path.joinpath(dirname, object_image_file_name)
            resized = Image.fromarray(square_image).resize(size)
            resized.save(dest)
            print(f'save {dest}')

        print('done.')

if __name__ == '__main__':
    make_datasets()

3.実行環境

AWS で実行します。
前出の実装のリポジトリに colab (colaboratory) での実行例が用意されています (CycleGAN.ipynb)。馬とシマウマのデータセットで学習を試してみたところ半日で終わらず、200 epoch のうち数 epoch しか進んでいません。与えられたデータを全部使った学習を200回まわすようになっていますが、そのうちの数回しかまわせていませんでした。おそらく colab では事前に学習済みのデータ (pretrained model) を使って生成を試すのを想定していそうです。これよりデータ量の多い今回の再現も colab では手にあまります。なので AWS を利用します。

機械学習の用途なので NVIDIA Deep Learning AMI の AMI を利用してみます。Docker で実行することも考えましたが、本題以外の部分でハマりたくないため、EC2 でそのまま実行していきました。事前に作成して S3 にアップしておいたデータセットを持ってくるために awscli や、必要なライブラリ (libffi-dev などが必要になるかもしれません) を導入します。

以下のサイズで動作を見ていきます。

  • t2.micro
    • S3 のリソースにアクセスできるかなど雑多な準備・確認用
  • g4dn.xlarge (T4 x 1GPU)
    • GPU を使って実行できるかどうかの確認用 (colab でも同程度の GPU なので期待はしない)
  • g4dn.12xlarge (T4 x 4GPU)
    • 複数 GPU を使えるかどうかの確認用 (あわよくば現実的な実行時間で済むかかもくらいに期待)
  • p3.16xlarge (V100 x 8GPU)
    • 強い GPU で実行した場合にどれくらいの実行時間になりそうか確認する用

p3.16xlarge (8GPU を利用し、バッチサイズが 36 になるよう指定して実行、イテレーションは 5000) で動作確認して 1 epoch どれくらいかかるか見てみたところ、およそ120秒となりました。すなわち 200 epoch 完了するのに数時間かかります。ここに3回ファインチューニングを重ねるためさらに時間がかかります。今回の再現がこのコストに見合うかというと微妙なところです。ひとさまがすでに論文として仕上げているものを再現するためだけにこれほどのコストをかけてよいものか、また再現する価値があったとしてその先はどうするのか、少し考える必要があるように思います。

実際のところ、この数時間ぶん程度の実行コストは機械学習のタスクとしては現実的な範囲に見えます。しかし、ここからさらに実用的なものを目指したり発展させていくなら検証をかさねることになります。この先進むには当初の動機が軽すぎるためコストをかける説得力がありません。そういうわけで、ここで一旦再現を中断することにしました。低コストで効率的に実行する方法を探ったり、計画を立てるなどして説得力を増す必要があります。

実践編 まとめと感想

中途半端な状態で終わってしまいましたが、論文に書かれた内容を追って、そこに込められた工夫を知れたのはよかったです。理論を整理して実際に動かし検証をやりきるのにたくさんのリソース (人的にも計算資源的にも) がかかることを考えると、論文をまとめることのすごさを感じました。今度はもうすこし具体的な道筋を考えるか、小さくはじめられるこころみでリベンジしていきたいです。

機械学習によるアイコン画像生成のこころみ (下調べ編)

0

何かと必要とされるアイコン画像を、人手をかけず気軽に作ることができたらうれしい! そんな夢をかなえたく、機械学習によるアイコン画像生成をこころみました。

今回こころみたこと

ここでは先行事例(くわしくは後述します)にならい、CycleGAN でのアイコン画像生成をこころみます。この下調べ編では仕組みについて見ていき、続く 実践編で具体的に動かしていきます。

すすめていくと、気軽な生成のためには気軽ではない準備が必要でした。またコストの面でも “機械学習で発生するものとしては現実的な範囲、ただし気軽に試すにはためらう程度” のリソースが必要になりました。今回のこころみでは気軽な範囲にとどめ、最後の一歩手前までを実践していきます。

動機

今回アイコン画像の生成をこころみた動機は主に以下の2点でした。

  1. 機械学習での生成をためしたい
  2. オリジナリティのあるアイコン画像を気軽に手に入れたい

1.機械学習での生成をためしたい

過去の案件で何かを予測したり識別したりするような課題を扱ったことはありますが、何かを生成するような課題については経験が少ないため、生成に関する知見を増やしたいです。

2.オリジナリティのあるアイコン画像を気軽に手に入れたい

システム開発では何かとアイコン画像の出番があります。しかも、対象のシステムに特化した “こういうアイコン画像が欲しいです” となることがたびたびあります。また、いろいろなアイコン画像を試してみたいという要望もしばしばあります。

特化したアイコンについては、様々なテイストのアイコンセットやニッチな領域に特化したアイコンが販売されているのでそれを利用する手もあります。とはいえピンポイントなものを探す手間はかかりそうです。

いろいろなアイコンを試してみたいという要望については、なるべくデザイナーの手を煩わすことなくアイコン画像の候補を用意したいところです。デザイナーの手にかかる前のプロトタイピングの段階で仮のそれらしいアイコン画像を用意できれば手戻りも減らせそうです。


上記では、一般的な用途のアイコン画像に加え、用途の偏ったアイコン画像を気軽にためしたいという要望があります。アイコン画像の生成については、あらかじめ用意されたアイコン画像の色調を変更したりアウトライン・塗り潰しを切り替えたりするなど、組み合わせで実現する方法もあります。ただしこの場合、バリエーションを用意するのに手がかかってしまうし、用意されたものから逸脱するアイコン画像を手に入れることはできません。

ここでは、任意の対象がアイコンとして表現されている画像が欲しい、と言えそうです。あらかじめ用意した選択肢をこえたものが欲しいというような問題の解決に機械学習の手法が使えないか、というのを理由に今回の課題を考えてみます。

課題設定

上述したとおり、機械学習の生成で “任意の対象がアイコンとして表現されている画像” が得られること、という課題に設定します。ぼんやりしたところを以下で詳しくしていきます。

そもそもアイコンとは何なのかを考える必要がありそうです。通常、アイコンは何かの対象を記号的に表現したものが多い印象です。簡潔な表現からそれが指す物体や概念を判別できるようなものです。今回は課題をわかりやすくするため、何かの “物体” を記号的に表現したものとしてアイコンを考えます。”概念” については、記号的に表現するのは難易度が高いため今回の課題の範囲外としました。

物体をアイコンとして表現するのに使えそうな手法として、今回は機械学習のスタイル変換 (style transfer) を候補としてみました。突然出てきたスタイル変換ですが、これについては “AI で画像をゴッホの画風に変換する技術” などと呼ばれているもので目にしたことがあるかと思います。A Neural Algorithm of Artistic Style の論文で jcjohnson/neural-style などの実装があります。このスタイル変換をアイコン画像の生成に利用できないかと考えました。

スタイル変換での画像生成について、以下の2つのパターンを検討してみました。

  • もともとアイコンではない何かの物体の画像をアイコンスタイルに変換する
  • もともとアイコン画像になっているものを異なるスタイルのアイコン画像に変換する

あわよくば、両者をあわせて 実写画像 → アイコン画像 → いろいろな表現のアイコン画像 という変換ができれば都合がよいです。

ひとまずここでは前者をみていきます。(ちなみに後者はまた別なメンバーがトライしました)

“機械学習のスタイル変換を使い、アイコンではない何かの物体画像をアイコン画像に変換することでアイコン画像を生成する” という課題としてみます。

事例をさがす

素人が考えつくようなアイディアなのでおそらく先例がありそうです。具体的な手法としてはスタイル変換関連のものを探せばよさそうですが、もうすこし詳しいキーワードが欲しいところです。ひとまずとっかかりとして『生成 Deep Learning (David Foster 著 オライリー・ジャパン発行)』を見てみます。画像についての生成の項目を見たところ “CycleGAN” と “ニューラルスタイル変換” というキーワードが出てきました。当初の方向性としても間違ってはいなそうなので、このあたりで調べてみます。

それらしいキーワードで検索していくと、やろうとしていることに近い先例 (というかソノモノな先例) に達したのでそれを見ていきます。

Iconify: Converting Photographs into Icons (arXiv.org)

IN THIS PAPER, WE TACKLE A CHALLENGING DOMAIN CONVERSION TASK BETWEEN PHOTO AND ICON IMAGES. ALTHOUGH ICONS OFTEN ORIGINATE FROM REAL OBJECT IMAGES (I.E., PHOTOGRAPHS), SEVERE ABSTRACTIONS AND SIMPLIFICATIONS ARE APPLIED TO GENERATE ICON IMAGES BY PROFESSIONAL GRAPHIC DESIGNERS. MOREOVER, THERE IS NO ONE-TO-ONE CORRESPONDENCE BETWEEN THE TWO DOMAINS, FOR THIS REASON WE CANNOT USE IT AS THE GROUND-TRUTH FOR LEARNING A DIRECT CONVERSION FUNCTION. SINCE GENERATIVE ADVERSARIAL NETWORKS (GAN) CAN UNDERTAKE THE PROBLEM OF DOMAIN CONVERSION WITHOUT ANY CORRESPONDENCE, WE TEST CYCLEGAN AND UNIT TO GENERATE ICONS FROM OBJECTS SEGMENTED FROM PHOTO IMAGES. OUR EXPERIMENTS WITH SEVERAL IMAGE DATASETS PROVE THAT CYCLEGAN LEARNS SUFFICIENT ABSTRACTION AND SIMPLIFICATION ABILITY TO GENERATE ICON-LIKE IMAGES.

ICONIFY : CONVERTING PHOTOGRAPHS INTO ICONS. / KARAMATSU, TAKURO; BENITEZ-GARCIA, GIBRAN; YANAI, KEIJI; UCHIDA, SEIICHI.

MMART-ACM 2020 – PROCEEDINGS OF THE 2020 JOINT WORKSHOP ON MULTIMEDIA ARTWORKS ANALYSIS AND ATTRACTIVENESS COMPUTING IN MULTIMEDIA. ASSOCIATION FOR COMPUTING MACHINERY, INC, 2020. P. 7-12 (MMART-ACM 2020 – PROCEEDINGS OF THE 2020 JOINT WORKSHOP ON MULTIMEDIA ARTWORKS ANALYSIS AND ATTRACTIVENESS COMPUTING IN MULTIMEDIA).

研究成果: CHAPTER IN BOOK/REPORT/CONFERENCE PROCEEDING › CONFERENCE CONTRIBUTION

CycleGAN で写真画像とアイコン画像のスタイル変換を試してみたところ「いい感じにアイコン風画像生成の抽象化ができた」ということなので、まさに求めているものという印象です。なお、見つけたときはこれを再現できれば目的が達成できそうだと大船に乗った気持ちでしたが、後々考えの甘さに気付きます (実証の完遂に敬意です)。

詳細は論文の本文を参照してもらうとして、ひととおり読んでみたところ以下がキモだと解釈しました。

  • CycleGAN を使う
  • 段階的に学習する
  • 目的にあうデータセットを使う

それぞれについて見ていきます。

なお、論文では以下の3つ、

  • “実写の人間の画像” と “単色白黒アイコンの人間の画像” で学習しての変換
    • 限定的な物体についての実写画像とアイコン画像との変換
  • “実写の物体の画像” と “単色白黒アイコンの画像” で学習しての変換
    • 物体全般についての実写画像とアイコン画像との変換
  • “実写の物体の画像” と “ロゴ画像” で学習しての変換
    • 物体全般についての実写画像とロゴ画像との変換
    • アイコン画像の話をしているところで突然ロゴ画像が出てきますがそれについては後述

が検証されていますが、より汎用的で良好な結果が得られたと思われる3つめの再現をこころみます。

CycleGAN を使う

CycleGAN とは何者なのか、というところから見ていきたいです。その前に GAN について軽く触れておきます。

GANとは何なのか?

GAN (敵対的生成ネットワーク, Generative adversarial networks) を Wikipedia で見てみると以下のように説明されています。

敵対的生成ネットワーク (てきたいてきせいせいネットワーク、英: GENERATIVE ADVERSARIAL NETWORKS、略称: GANS)は、2014年にイアン・グッドフェローらによって発表された教師なし学習で使用される人工知能アルゴリズムの一種であり、ゼロサムゲームフレームワークで互いに競合する2つのニューラルネットワークのシステムによって実装される[1]。

GANSは生成ネットワーク(GENERATOR)と識別ネットワーク(DISCRIMINATOR)の2つのネットワークから構成される。例として画像生成を目的とするなら生成側がイメージを出力し、識別側がその正否を判定する。生成側は識別側を欺こうと学習し、識別側はより正確に識別しようと学習する。このように2つのネットワークが相反した目的のもとに学習する様が敵対的と呼称される所以である。

HTTPS://JA.WIKIPEDIA.ORG/WIKI/%E6%95%B5%E5%AF%BE%E7%9A%84%E7%94%9F%E6%88%90%E3%83%8D%E3%83%83%E3%83%88%E3%83%AF%E3%83%BC%E3%82%AF (2020年10月20日 (火) 19:27 時点の版)

ざっくり言えば、

  • 生成する役と識別する役が互いに高めあうように学習して、上手に生成ができるようになる仕組み
  • ニューラルネットワークで作られている (ここでのニューラルネットワークはディープラーニングの一種と言ってよさそうです)

というものです。

CycleGANとは何なのか?

戻って CycleGAN についてです。これは論文の本文をざっと要約してみます。

CycleGAN はドメイン変換手法で、一対一で対応する画像の情報なしで2つのドメイン間のマッピングを決めることができます。今回のケースで言えば、実写の物体の画像とアイコン画像という2つのドメインについて、実写の物体とアイコンの一対一の対応関係の情報なしでそのマッピングを決めることができます。今回のような課題の場合、実写の車の画像と車を表わすアイコン画像といった組み合わせを用意することは非現実的です。pix2pix で使うようなデータを用意することは難しいでしょう。

CycleGAN では双方向に一対一のマッピングを実現するために “cycle-consistency loss” を使っています。前出の『生成 Deep Learning』の用語で言うなら “復元性損失” と訳されるものでしょうか。今回で言えば実写の物体の画像とアイコン画像の変換を双方向に行います。双方向の変換が上手にできるならば、実写の物体をアイコン画像に変換し、さらにそのアイコン画像を実写の物体の画像に変換すると元の実写の物体の画像とよく似たものを作れるはずです。

ざっくり言えば、

  • 2つのドメイン間の対応情報なしにマッピングを決めることができる
  • 双方向に変換する仕組みを使っている

というものです。より詳細は論文の本文や CycleGAN の原論文を参照してください。なお CycleGAN も、馬とシマウマの変換 (Unpaired Image-to-Image Translation using Cycle-Consistent Adversarial Networks) で有名です。

実装は junyanz/pytorch-CycleGAN-and-pix2pix を利用したとのことなので、これにならいます。

補足: CycleGAN では “identity mapping loss” (同一性損失) という色の不変性に関連する仕組みが使われています。実写画像と白黒アイコン画像の変換を検証する際に、色は重要な要素ではないためこの損失を弱めたとあります。今回は実写の物体の画像とロゴ画像とを利用するパターンの再現を目標としているので、とくに手心を加えずやっていきます。

段階的に学習する

学習につかうデータセットのバリエーションに対してうまく対処するため、段階的な学習という手段を使ったとあります。

実写の物体の画像とアイコン画像との間の変換は、馬とシマウマのときのように特定の対象同士を扱うものではありません。論文中の検証のうちの1つめ、”実写の人間の画像と単色白黒アイコンの人間の画像で学習しての変換” は、馬とシマウマのケースに近いと考えられます。しかし “実写の物体” の画像は人間だけでなく、車やボールなどいろいろなバリエーションがあります。またアイコン画像についても、それぞれが全く異なる抽象化の施された表現になっています。このバリエーションへ対応するために PGGAN という手法にならい、段階的な学習で対処しています。今回は前出の CycleGAN の実装で --continue_train フラグをつけてモデルをファインチューニングしていくことになります。

PGGAN (tkarras/progressive_growing_of_gans) という新しいワードが出てきました。これはざっくり言えば “低解像度の画像から学習をはじめて層を増やしていくと訓練の速度があがり、安定性が向上する” というものです。32×32 ピクセルのサイズから 64×64 → 128×128 → 256×256 と段階的にファインチューニングして学習をしたとあります。

目的にあうデータセットを使う

今回は “実写の物体の画像とロゴ画像で学習しての変換” を再現するため、以下のデータセットを用意します。

  • 実写の物体の画像として COCO – Common Objects in Context
    • 物体認識やセグメンテーション、キャプションのアノテーションデータと画像を提供するデータセットです
    • 今回はアノテーションとして “2017 Train/Val annotations” を、画像データとしてそれに対応する “2017 Train images” をもとにデータを作成します
    • アノテーションの情報をもとに、画像から物体だけを切り抜き白背景にして正方形にし、リサイズして使います
  • ロゴ画像として LLD – Large Logo Dataset
    • favicon や Twitter のプロフィール画像を集めたデータセットです
    • 今回は LLD-logo (Twitter のプロフィール画像をロゴととらえ集めたもので、400×400 ピクセルの画像) からランダムに選んだ 20000 画像をリサイズして使います

実写の物体の画像

実写の物体の画像をアイコン画像に変換するにあたり、その元となる実写の物体を切り出す必要があります。アイコン画像は通常、背景持っていません。ただ、そのような画像のデータセットは存在しないので、COCO のデータセットをアノテーションの情報で切り抜きデータを作成しています。ここで使うアノテーション情報は、ピクセル単位で画像のどこに何の物体があるかという情報を使います。

また、対象の物体が小さすぎる場合も除外します。COCO のアノテーション情報は、ある画像内に存在する物体の領域の情報なので、対象が小さく写っていたり部分的に写っているものも多いです。本来ならば対象がわかりやすく写っている画像が好ましいのですが、そのようなデータセットは存在しないため COCO をよしなに加工して利用しています。結局のところ、今問題としているのは識別ではなく生成なので、アイコンとして生成したい見栄えのよい画像が用意できるとうれしいです。

ロゴ画像

論文内では、実写の物体の画像と白黒のアイコン画像とを使った検証も行なっていますが、今回は以下の理由から白黒アイコン画像での再現を見送りました。

  • Microsoft PowerPoint で提供されている白黒アイコン画像を使ったとあるものの、そもそもそのアイコン画像たちを特定できていない
  • 数が少なく、別途データ拡張が必要 (オリジナルの画像を回転・拡縮・ノイズ追加をしてデータを水増しする工夫が必要)
  • 白黒アイコン画像の場合には同一性損失を弱めたとあるものの (前述)、どの程度弱めたのかは詳しく言及されていないため試行錯誤の必要がある

ロゴはテキストを含んでいたり色があったりと、その用途と形状に差異はあるものの、抽象的なデザインという点でアイコンに似ているためアイコン画像とともに試されています。検証でも悪くない結果を得られたようなので、ロゴ画像で再現をこころみます。ロゴ画像については LLD のデータセットで十分な数が提供されているためデータ拡張が不要な点もありがたいです。

下調べ編 まとめ

ざっくりまとめます。

  • アイコン画像の生成に CycleGAN が使えそう
  • ただし段階的な学習などひと工夫が必要
  • データセットもぴったり要件にあうものはないのでひと工夫必要

スタイル変換でアイコン画像を生成できないか?というあいまいな状態からすこし具体的になってきました。以上に見てきた内容をもとに画像生成を実践してみます。実践編に続きます

AWS Global Acceleratorの紹介&速度検証

0

はじめに

データイノベーション部浅田です。

アプリケーションにとって、どれだけサクサク動くかというのは重要な指標の一つです。Webアプリケーションやモバイルアプリケーションなどのネットワークの利用を前提としたアプリケーションにおいては、ネットワークのレスポンスの良さ、というのも重要なファクターになります。

せっかく情熱などをもって構築したサービスも、コンテンツの表示に時間がかかってしまうと「何よりも、速さが足りない!」と思われてしまいかねません。

そこで、今回ご紹介するサービスがこちら!

AWS Global Accelerator(以下Global Accelerator)

となります。

より詳しい特徴は上記をご確認頂ければと思いますが、色々あるメリットのうち、今回お伝えしたい内容としては、こちらのサービスを使うとネットワーク速度改善のメリットが得られるという点です。

「ネットワーク速度」はインターネットサービスとして限りなく速いことが望ましいです。そこで今回は、上記の二点について、Global Acceleratorを使わなかった場合と使った場合にどれだけかわるのかを検証して見たいと思います。なお、EC2にNginxをインストールし、そのレスポンスを確認する、という手順で見ていきます。

検証

前提

EC2インスタンスタイプ: m5.large
Nginx: 1.18.0
クライアント: curl 7.54.0
場所: アピリッツ社内(東京都渋谷区)

[EC2 IP]
東京: 54.250.246.155
バージニア: 34.229.65.223

[Global Accelerator IP]
75.2.96.126
99.83.178.155

なお、速度の比較として、10回読み込みを行い、その平均値を計測するものとします。

準備

東京リージョンとバージニア北部リージョンとにEC2を起動して、以下のコマンドでnginxのインストールおよびダミーファイルを準備します。

# EC2内で実行
sudo amazon-linux-extras install nginx1
cd /usr/share/nginx/html/
sudo dd if=/dev/zero of=1M.dummy bs=1M count=1
sudo dd if=/dev/zero of=20M.dummy bs=1M count=20
sudo service nginx start

計測用に以下のスクリプトをspeed-test.shの名前でローカルに用意します。

# 接続
echo "### サンプリング(秒)"
for i in {1..10}; do curl -XGET -w "%{time_total}\n" -o /dev/null -s ${1}; done | tee tmp.lst

# 平均値出力
echo "### 平均(秒)"
awk '{sum+=$1} END {print sum/NR}' tmp.lst
rm tmp.lst

最後に、Global Acceleratorを作成し、東京リージョンのEC2にエンドポイントの向き先を設定します。以上で、準備完了です。

第一弾 東京リージョン

第一弾として、東京リージョンへのアクセスでのGlobal Accelerator有無の速度についての比較をします。

1Mのファイル

まずは、直接EC2にアクセスします。

$ sh speed-test.sh http://54.250.246.155/1M.dummy
### サンプリング(秒)
0.109332
0.119329
0.131457
0.129000
0.115801
0.110114
0.132545
0.113515
0.112620
0.111140
### 平均(秒)
0.118485

次にGlobal Accelerator経由です。

$ sh speed-test.sh http://99.83.178.155//1M.dummy
### サンプリング(秒)
0.109456
0.105758
0.107199
0.107842
0.105607
0.108402
0.110008
0.104493
0.106547
0.109290
### 平均(秒)
0.10746

ん?少し早くなったかな、ぐらいでほぼ差はないですね。

20Mのファイル

直接EC2へのアクセスの場合を計測します。

$ sh speed-test.sh http://54.250.246.155/20M.dummy
### サンプリング(秒)
1.816273
1.810556
1.807303
1.802766
1.808038
1.808243
1.800309
1.804496
1.986049
1.805717
### 平均(秒)
1.82498

次にGlobal Accelerator経由です。

$ sh speed-test.sh http://99.83.178.155/20M.dummy
### サンプリング(秒)
1.802430
1.806430
1.804574
1.802140
1.800463
1.798066
1.802565
1.798186
1.846157
1.800256
### 平均(秒)
1.80613

ほぼ変わらないですね。

Global Acceleratorはアクセス元が対象リージョンに近いとそのメリットをあまり享受できないようです。

第二弾 バージニア北部リージョン

次に、国外のリージョンであるバージニア北部リージョンへのアクセスでのGlobal Accelerator有無の速度についての比較をしたいと思います。Global Acceleratorのエンドポイントをバージニア北部リージョンのEC2に切り替えます。

1Mのファイル

まずは直接EC2へのアクセスのケースです。

$ sh speed-test.sh http://34.229.65.223/1M.dummy
### サンプリング(秒)
3.134302
3.162077
3.117981
3.098290
3.150670
3.066146
3.134135
3.137177
3.134533
3.180120
### 平均(秒)
3.13154

次にGlobal Accelerator経由の場合です。

sh speed-test.sh http://99.83.178.155/1M.dummy
### サンプリング(秒)
1.040463
1.034937
1.036202
1.040337
1.032864
1.034404
1.035367
1.032810
1.041944
1.032675
### 平均(秒)
1.0362

お、およそ三倍の速度が出ているようです。

20Mのファイル

まずは直接EC2へのアクセスの場合です。

$ sh speed-test.sh http://34.229.65.223/20M.dummy
### サンプリング(秒)
7.312831
5.675996
6.660435
12.293564
7.569658
16.370434
13.757100
8.670905
16.401453
8.794712
### 平均(秒)
10.3507

時間もそこそこかかってますが、今までに比べてバラツキが大きくなっているのも気になります。(念のため、数回サンプリングしてみましたが、どのケースもバラツキは大きかったです。)

次にGlobal Accelerator経由です。

$ sh speed-test.sh http://99.83.178.155/20M.dummy
### サンプリング(秒)
2.739648
2.741390
2.741749
2.737428
2.763309
2.729312
2.731547
2.742664
2.736493
2.772755
### 平均(秒)
2.74363

かなり早くなりました。7秒も世界を縮めてしまいました。そして、ばらつきもほとんどなく、安定した速度が出ています。ついに見つけました、Global Acceleratorの真髄を!

第三弾 東京リージョン内のEC2からバージニア北部リージョンのEC2へのアクセス

第一弾と第二弾とでは、ユーザのアクセスを想定して筆者のローカルからアクセスして計測してみましたが、最後に東京リージョンのEC2からバージニア北部リージョンのEC2へアクセスした際の時間を計測してみます。

1Mのファイル

まず、直接EC2です。

$ sh speed-test.sh http://34.229.65.223/1M.dummy
### サンプリング(秒)
1.370514
1.372094
1.367089
1.380025
1.339979
1.375507
1.333260
1.373431
1.338106
1.367856
### 平均(秒)
1.36179

素でもかなり速くなっています。AWS内の回線品質の良さを伺わせます。

次にGlobal Accelerator経由です。

$ sh speed-test.sh http://99.83.178.155/1M.dummy
### サンプリング(秒)
0.870017
0.873519
0.872324
0.867491
0.870899
0.874320
0.875362
0.870478
0.873536
0.869653
### 平均(秒)
0.87176

倍とまではいきませんが、十分速くなっています。EC2内からアクセスした際にも、Global Acceleratorの恩恵は得られるということですね。

20Mのファイル

直接EC2の場合を計測します。

$ sh speed-test.sh http://34.229.65.223/20M.dummy
### サンプリング(秒)
3.528554
3.487068
3.753335
3.572857
3.675303
3.662903
3.599749
3.639234
3.552648
3.611756
### 平均(秒)
3.60834

ローカル環境からのアクセスに比べて十分に高速であるとともに、速度の安定度も感じられます。

次に、Global Accelerator経由です。

$ sh speed-test.sh http://99.83.178.155/20M.dummy
### サンプリング(秒)
2.467313
2.235525
2.159171
2.311107
2.023744
2.461509
2.320583
2.027042
2.169427
2.033224
### 平均(秒)
2.22086

さらに速くなっていますね。

検証結果

計測された、速度改善率をまとめると以下の通りです。

ロケーション1Mファイル20Mファイル
ローカル to 東京リージョン約9%約1%
ローカル to バージニア北部リージョン約67%約73%
東京リージョン to バージニア北部リージョン約36%約38%

以上のことより、Global Acceleratorは特に離れたリージョンへのアクセス改善に効果を発揮するということが言えると思います。また、ファイルサイズが大きい方がメリットも大きくなった結果となりました。

まとめ

Global Acceleratorを使用することで、特に遠く離れたリージョンのサービスにアクセスする際に、かなり速度面でメリットを得られることがわかりました。特に大きなファイルをダウンロードする際には、単純な速度面もさることながら、安定した通信環境につなげるというのもメリットとなるかとおもいます。

今回は速度面に焦点を当てましたが、Global Acceleratorはその他にも利点があります。例えば、グローバルにサービスを展開している場合には、それぞれのリージョンのApplication Load Balancingの前段に配置することで、指定したWeightに応じてリクエストを各リージョンに割り振ることもできます。一つのリージョン内で運営する際にも、Blue Greenデプロイに活用することも可能でしょう。

また、Application Load BalancingではIPアドレスは可変のため、CNAMEで名前解決するように設定しますが、Apexドメインで名前解決する際にはCNAMEが設定できないことが問題になったりするケースも存在します。ですが、Global Acceleratorの場合は固定IPが振られるため、Aレコードで指定できるので、Apexドメインの問題が解消されます。

以上、Global Acceleratorの紹介&速度検証でした。

WEBマーケティング担当者が息抜きに見るサイト3覧

0

こんにちは。DB部の有馬です。

現在はマーケティンググループに所属していて、普段はGoogleアナリティクスを使ってクライアントのサイトにある課題を見つけたり、WEB広告の運用などをしています。

マーケティング関係の仕事はとても興味深く面白い部分も多いのですが、如何せん自分は集中力を持続させるのが苦手なので、8時間ずーっと手を動かし続けることができません。

なので、1日に2回くらいは息抜きにメディアサイトを見て気分をリセットすることにしています。

今回の記事では、そんな自分が息抜きに見てるサイトを紹介しようかと思います。

一応マーケティング関係のサイトが多いので、息抜きとはいえ勉強にはなっているはず・・・・です。

MarkeZine

■ヒトコトで言うと

「広告・マーケティングの最新情報がわかる!マーケター向け専門メディア」

■概要

毎日新しいマーケティング系の記事が更新されるWEBメディアです。読む頻度は一番高い。

更新頻度の高さもさることながら、とりあげられるテーマはどれも興味深いものが多く、タイトルを見るだけで読んでみたくなる記事ばかり。

会員システムがあり、一部の記事は会員にならないと読めませんが大体は未ログインでも読めます。(面白そうなタイトルのものは7割くらい会員にならないと読めないのがこのサイトの上手いところです。)

毎日更新されているのでその時その時で流行している話題が取り上げられることが多く、マーケティングに興味のない人でも楽しめる記事が多いのでぜひページを開いてみてください。

■URL

https://markezine.jp/

ITmediaマーケティング

■ヒトコトで言うと

「マーケ×ITのいまがよくわかる」

■概要

こちらもマーケティング系のメディアサイトです。

前述のMarkeZineと比べるとIT系の技術とマーケティングを組み合わせた話題・技術を取り上げた記事が多いサイトであり、技術系のトレンドを

追っている人であれば気になるようなタイトルの記事がズラッと並んでいます。

最近だと、サードパーティーCookieの利用制限によるデジタル広告への影響を取り上げた記事が特に面白かったですね。

「サードパーティーCookieの利用制限はデジタル広告にとって大きなチャンスでもある」

ただ会員登録をしてないと記事を読めないので、ひと手間は必要になります。(自分は登録しました。)

■URL

https://marketing.itmedia.co.jp/

note

■ヒトコトで言うと

「つくる、つながる、とどける。」

■概要

こちらはメディアというより記事投稿サイトですね。知っている方も多いのではないでしょうか。

マーケティング系の記事はもちろん、グルメ、ライフスタイル、デザイン、IT、漫画、ゲームなどありとあらゆるジャンルの記事が集まっています。

誰でも投稿できるので、地元の中学生が投稿している場合もあればプロのライターが投稿している場合もあり、内容は千差万別。

内容が充実していて勉強になる記事を見つけるのはなかなか骨が折れますが、その分見つけたときは非常に得した気持ちになれます。

読み物が好きな人はたまに覗いてみると、楽しい記事に出会えるかもしれませんね。

ちなみに自分は「はてなブログ」の方が好きです。

■URL

https://note.com/

以上の3つが、自分の気に入っているサイトです。

どのサイトもコンテンツが多く、全部読もうと思ったら余裕で1日は使ってしまいますが、1~2記事読む程度なら5分程度で終わります。

ちょっと集中力落ちて来たな、と思ってきたら是非思い出してみてくださいね。

最近人気な記事