PyTorchのImageFolderで読み込み済みの画像をキャッシュする

PyTorchでCNNを組んで画像を識別する学習を回していて,ふとプロファイリング(http://shiba6v.hatenablog.com/entry/2018/05/15/215211)をとってみると,

         424113812 function calls (419713376 primitive calls) in 25020.907 seconds

   Ordered by: internal time
   List reduced from 466 to 10 due to restriction <10>

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
        1 8992.740 8992.740 25020.906 25020.906 <ipython-input-2-0a878bac24c8>:186(<module>)
  2661000 6994.380    0.003 6994.380    0.003 {method 'decode' of 'ImagingDecoder' objects}
  7012500 3792.518    0.001 3792.518    0.001 {method 'nonzero' of 'torch._C._TensorBase' objects}
    68750 1436.746    0.021 1436.746    0.021 {method 'run_backward' of 'torch._C._EngineBase' objects}
  1099950 1280.304    0.001 1280.304    0.001 {method 'resize' of 'ImagingCore' objects}
   412500  767.758    0.002 4908.700    0.012 <ipython-input-2-0a878bac24c8>:137(unary)
  8774486  231.978    0.000  231.978    0.000 {method 'mean' of 'torch._C._TensorBase' objects}
    68750  163.959    0.002  190.920    0.003 <ipython-input-2-0a878bac24c8>:144(kde_batch)
  1168700  143.284    0.000  143.284    0.000 {method 'float' of 'torch._C._TensorBase' objects}
  1091900  108.316    0.000  108.316    0.000 {method 'copy' of 'ImagingCore' objects}

ん?? ImagingDecoderがめっちゃ時間を食っている・・・
画像の読み込みのデータセットtorchvision.datasets.folder.ImageFolderを使っていたんですが,どうやら毎回画像ファイルを読みに行っているっぽい・・・?
50epoch回してImagingDecoderが一番時間がかかっているなら,PyTorch側でキャッシュはされていなそうですね.

今回は学習データがメモリに乗り切りそうだったので,データセットを全部メモリにキャッシュしてあげて高速化します.
transformにランダムに切り出すような処理を今回は書いていないので,今回は__getitem__の出力をそのままdictionaryに入れます. ImageFolderと変わらない感じで使えるようにしました.(好きにパクって使ってください.)

class CachedImageFolder(torchvision.datasets.folder.ImageFolder):
    def __init__(self, root, transform=None, target_transform=None,loader=torchvision.datasets.folder.default_loader):
        super(CachedImageFolder, self).__init__(root,transform=transform,target_transform=target_transform,loader = loader)
        self.cache = {}
    def __getitem__(self,index):
        if index in self.cache:
            return self.cache[index]
        item = super(CachedImageFolder,self).__getitem__(index)
        self.cache[index] = item
        return item

CachedImageFolderを使って10epoch程度回した結果,

         22530602 function calls (21791255 primitive calls) in 3017.442 seconds

   Ordered by: internal time
   List reduced from 796 to 10 due to restriction <10>

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
        1 1508.861 1508.861 3008.220 3008.220 <ipython-input-10-ed3ddfcf5be8>:186(<module>)
  1177999  637.229    0.001  637.229    0.001 {method 'nonzero' of 'torch._C._TensorBase' objects}
    11549  346.354    0.030  346.354    0.030 {method 'run_backward' of 'torch._C._EngineBase' objects}
    69295  149.182    0.002  853.208    0.012 <ipython-input-10-ed3ddfcf5be8>:137(unary)
    53220  140.252    0.003  140.252    0.003 {method 'decode' of 'ImagingDecoder' objects}
  1475069   42.256    0.000   42.256    0.000 {method 'mean' of 'torch._C._TensorBase' objects}
    11549   32.591    0.003   37.861    0.003 <ipython-input-10-ed3ddfcf5be8>:144(kde_batch)
    21999   25.677    0.001   25.677    0.001 {method 'resize' of 'ImagingCore' objects}
    11550   20.518    0.002   20.518    0.002 {built-in method stack}
    23100   14.861    0.001   14.861    0.001 {method 'to' of 'torch._C._TensorBase' objects}

おっ,ImagingDecoderの順位が下がっていますね. 元が50epochで25000sec,キャッシュを利用したら10epochで3000secなので,(ちゃんとした比較ではないですが)速くなっていそうですね

これ,もしメモリに載らなくてもSwap領域を増やしたらいけそうな気がしますが,それは必要になったらやりたいと思います. (大きな画像をリサイズするとかなり容量が落ちるのでなんだかんだで載ると思いますが・・・w)

他に便利なモジュールなどがあれば教えてほしいです ><

PyTorchのDataParallelのモデルを保存する

PyTorchで複数GPUで学習させる場合,

model = nn.DataParallel(model)

のようにDataParallelで保存しますが,このモデルを保存したい場合にcuda runtime error : out of memoryが出ることがあります.
その場合は,下のようにDataParallelから元のモデルを取り出してCPUのモデルに変えてあげることで保存できるようになります.

torch.save(model.module.cpu(),file_path)

読み込み時はこうすればOK

new_model = torch.load(file_path)

参考

Optional: Data Parallelism — PyTorch Tutorials 1.0.0.dev20181002 documentation

cProfileを使ってPythonでの計算時間を測定する

最近は,4回生になり研究室に配属されて画像処理の勉強をしています. 論文を読んでそれを実装してみるという流れで勉強していますが,REPLでnumpyの行列計算のコードを打っていると,目立って時間がかかる行があることが分かります. そこで,繰り返し呼ぶ処理や重い処理にかかる時間を,定量的に調べたいと思いました.

やりたいこと

  • スクリプト全体で,時間がかかっている箇所を調べたい
  • 遅い処理を見つけて高速化したい
  • できるだけ簡単にプロファイリングしたい

環境・使用ライブラリ

  • Ubuntu 16.04.4 LTS
    • WSL上で動かしています
  • Python 3.5.2
  • cPofile
  • pstats

Pythonで使えるプロファイラについて調べてみると,cProfileとline_profilerという2つのプロファイラがあることが分かりました. line_profilerを使う場合は関数に@profileというデコレータを追加する必要があり,コードを書き換えずにREPLで試したいので今回はパスしました.Pythonに標準で入っているcProfileを使うことにしました.pstatsはプロファイリング結果を表示できるモジュールです.

方法

時間を計測したいコードの前に以下のコードを貼り付けて,プロファイラを有効にします.

import cProfile
import pstats
c_profile = cProfile.Profile()
c_profile.enable()

計測したいコードの後に以下のコードを貼り付けます. print_stats(10)はtottime(そのメソッドにかかった時間の合計)の上位10個をとってくるという意味です.

c_profile.disable()
c_stats = pstats.Stats(c_profile)
c_stats.sort_stats('tottime').print_stats(10)

全体をプロファイラにかける

結果

書いていたスクリプト(本来は貼るべきですが,説明すると長くなりそうなので省略)をプロファイラにかけると,6.8秒もかかっていて,そのうちのほとんどがnumpy/linalg/linalg.py:1299(svd)にかかっていることが分かりました.

        267323 function calls (261982 primitive calls) in 6.844 seconds

   Ordered by: internal time
   List reduced from 2743 to 10 due to restriction <10>

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
        1    4.634    4.634    4.634    4.634 /usr/local/lib/python3.5/dist-packages/numpy/linalg/linalg.py:1299(svd)
        1    1.082    1.082    1.082    1.082 {built-in method numpy.core.multiarray.matmul}
       16    0.195    0.012    0.195    0.012 {imread}
       28    0.116    0.004    0.121    0.004 {built-in method _imp.create_dynamic}
      286    0.083    0.000    0.099    0.000 <frozen importlib._bootstrap_external>:816(get_data)
        1    0.078    0.078    5.793    5.793 /usr/local/lib/python3.5/dist-packages/numpy/linalg/linalg.py:1652(pinv)
      286    0.062    0.000    0.062    0.000 {built-in method marshal.loads}
1273/1218    0.027    0.000    0.119    0.000 {built-in method builtins.__build_class__}
     1269    0.022    0.000    0.022    0.000 {built-in method posix.stat}
      286    0.016    0.000    0.016    0.000 {method 'read' of '_io.FileIO' objects}

考察

コード中に x = np.dot( np.linalg.pinv(A) , b) という部分があり,そこがnp.linalgを使っていたので遅そうだと考えました. この部分はこの記事の本題とは関係ありませんが,  A {\bf x} = {\bf b} を解いています. 優決定系(変数の数より連立方程式の数が多い)の行列で最小二乗誤差が小さくなるようなxを求める式です.詳しくはこちらのサイトに書いてあります.

最小二乗法とフィッティングとモデルパラメータ推定(アマチュア用)

行列計算を改善する

先ほど遅かった部分の計算時間を見るために,次のコードをREPLに貼り付けました.

import cProfile
import pstats
c_profile = cProfile.Profile()
c_profile.enable()

x = np.dot( np.linalg.pinv(A) , b)

c_profile.disable()
c_stats = pstats.Stats(c_profile)
c_stats.sort_stats('tottime').print_stats(10)

結果

         51 function calls in 5.461 seconds

   Ordered by: internal time
   List reduced from 29 to 10 due to restriction <10>

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
        1    4.353    4.353    4.353    4.353 /usr/local/lib/python3.5/dist-packages/numpy/linalg/linalg.py:1299(svd)
        1    1.026    1.026    1.026    1.026 {built-in method numpy.core.multiarray.matmul}
        1    0.079    0.079    5.458    5.458 /usr/local/lib/python3.5/dist-packages/numpy/linalg/linalg.py:1652(pinv)
        1    0.003    0.003    0.003    0.003 {built-in method numpy.core.multiarray.dot}
        1    0.000    0.000    0.000    0.000 {method 'reduce' of 'numpy.ufunc' objects}
        3    0.000    0.000    0.000    0.000 /usr/local/lib/python3.5/dist-packages/numpy/core/numeric.py:424(asarray)
        1    0.000    0.000    0.000    0.000 /usr/local/lib/python3.5/dist-packages/numpy/core/fromnumeric.py:2222(amax)
        3    0.000    0.000    0.000    0.000 {built-in method numpy.core.multiarray.array}
        3    0.000    0.000    0.000    0.000 {method 'astype' of 'numpy.ndarray' objects}
        1    0.000    0.000    0.000    0.000 <stdin>:1(<module>)

考察

ここでやはり4秒程度かかっていたことが分かります. これまでは, A {\bf x} = {\bf b} を解くときに[tex: AT A {\bf x} = AT {\bf b}] から疑似逆行列(np.linalg.pinv(A))を求めて[tex: {\bf x} = (AT A)^{-1} AT {\bf b}] を計算して解いていました. それをやめて,lstsqという最小二乗法のメソッドを使ってnp.linalg.lstsq(A.T @ A, A.T @ b)とする方が効率的かもしれないと思いました.

改善して比較する

先ほどと比較するために,次のコードをREPLに貼り付けました.

import cProfile
import pstats
c_profile = cProfile.Profile()
c_profile.enable()

AT =A.T
x,res,rank,s = np.linalg.lstsq(AT @ A, AT @ b)

c_profile.disable()
c_stats = pstats.Stats(c_profile)
c_stats.sort_stats('tottime').print_stats(10)

結果

         122 function calls in 0.389 seconds

   Ordered by: internal time
   List reduced from 46 to 10 due to restriction <10>

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
        2    0.383    0.192    0.383    0.192 {built-in method numpy.linalg.lapack_lite.dgelsd}
        2    0.003    0.002    0.003    0.002 {built-in method numpy.core.multiarray._fastCopyAndTranspose}
        1    0.001    0.001    0.001    0.001 {method 'write' of '_io.TextIOWrapper' objects}
        8    0.000    0.000    0.000    0.000 {built-in method posix.stat}
        1    0.000    0.000    0.389    0.389 /usr/local/lib/python3.5/dist-packages/numpy/linalg/linalg.py:1880(lstsq)
        5    0.000    0.000    0.000    0.000 {built-in method numpy.core.multiarray.zeros}
        1    0.000    0.000    0.000    0.000 /usr/lib/python3.5/linecache.py:82(updatecache)
        1    0.000    0.000    0.002    0.002 {built-in method _warnings.warn}
        7    0.000    0.000    0.000    0.000 /usr/lib/python3.5/posixpath.py:71(join)
        1    0.000    0.000    0.000    0.000 {method 'reduce' of 'numpy.ufunc' objects}

は,速い・・・

考察

4秒以上かかっていた先ほどと比べて,0.389秒とかなり速くなっていることが分かりました.

感想

REPLでもプロファイラを使って実行時間を比較できることが分かりました. 処理が遅いときに原因となっている箇所を探すのに使えそうです. CliborやClipyのスニペットに追加しておくと便利そうだと思いました. メソッドごとに見られるline_profilerも便利そうなので,cProfileに飽きてきたらそちらも使ってみようと思います.

OVRPhonemeContext.Start ERROR: Could not create Phoneme context.

概要

Unityでリップシンクをしようとして、OVRLipSyncを使ったらエラーが出た。

OVRPhonemeContext.Start ERROR: Could not create Phoneme context.

f:id:shiba6v:20180301205522p:plain デモと同じはずなのに、動かず・・・

原因(?)

コードを読んでたどっていくと、結局はOVRLipSyncのDLLのメソッドの実行がうまくいっていないっぽい(?)

解決法

OVRLipSync.csはシーン上で1つのみ配置するべきコンポーネントであるが、これをいったん外し、再度付けるとうまくいった。

おわりに

何故直ったかわからないが、このエラーメッセージでググっても解決策が出なかったので、この現象に悩まされている人がいれば参考にしてほしい。

過去問サイトを自動生成する

大学の過去問サイトを自動生成するプロジェクトを作った. GoogleDriveに過去問を入れて,Usageに従って使うと簡単(これを簡単と言って良いのか・・・?)に過去問サイトが作れます.

最初は雑にRailsでやっていたけれど,過去問の量ならDBをつかわないで静的ページにした方がBitballoonにも置けて速くて良い気がしたので,シンプルな過去問サイト作成プログラムにした. HTMLとかCSSが書けると,もっとカスタマイズできる.

サーバー代もかからないし更新も簡単なので,いろんな人に使ってほしいな〜

github.com

Unityでプレビュー時に毎回SteamVRが立ち上がるのをやめさせたい

UnityでSteamVR Pluginを導入して開発中、UnityEditor上でプレビューするたびにSteamVRが立ち上がります。 この機能は、HMDを使うときはありがたいのですが、SteamVR Pluginを導入してやっぱりやめた時やVR HMDを使わずにプレビューするときなどにSteamVRが勝手に立ち上がるのは不便です。

f:id:shiba6v:20180217034352p:plain

私は、Timelineで作った映像をムービーキャプチャでキャプチャしたかったのですが、Profilerで見たときにXR.WaitForGPUが邪魔をしてフレームレートが30fpsを大きく切ってしまったので、ムービーキャプチャを使う際は一時的にSteamVRを利用しないようにする必要がありました。

以下に、SteamVRが勝手に立ち上がらないようにする方法を書きます。 まず、ツールバー/Edit/Project Settings/Playerを開きます。 すると、こういったPlayer Settingの画面が出てきます。 このXR SettingsのVirtual Reality Supportedのチェックを外せばOKです。 f:id:shiba6v:20180217033813p:plain

よくよく考えればそりゃ当然だという感じですが、ちょっと困ったのでメモとして残しておきます。

追記(2018/04/24)

この設定をしても,まだ自動でVirtualRealitySupportedが自動で勝手にONになってしまいます. 先程設定した - Project Settings -> Player -> Virtual Reality Supported をOFFにする他に - Preferences -> SteamVR -> Automatically Enable VR もOFFにすれば良いそうです.

参考 Initializing OpenVR manually in C# :: SteamVR Developer Hardware General Discussions

Mercari BOLD Internshipでアメリカに行ってきた話

この記事はCAMPHOR- Advent Calendar 2017 13日目の記事です. CAMPHOR- は京都のIT系学生のためのコミュニティです.興味がある人は,遊びに来てくれると嬉しいです.

はじめに

この記事には,Mercari BOLD Internship 2017 GLOBALというインターンに参加した時の記録を日記のような形でまとめた.このインターンについてざっくり言うと,学生エンジニアと学生プランナーが2人1組でアメリカやイギリスに行って,メルカリが世界で戦うためのアイディアを考えてくる,ということだ.

このインターンに応募した理由は2つあって,アメリカに行ってアメリカ人の文化を直接お話をすることでよく知りたいと思ったこと,これからウケるアプリやサービスを作ろうとするならユーザーヒアリングを体験してみるのも役に立ちそうだと思ったことの2つだった.

メルカリのBOLD Internshipは以前にも行われていたが,その時は応募のタイミングを逃した.今回は別の海外に行く系のイベントに落選して海外に行きたさが高まっていたこともあり,思い切って応募した.

この記事には,メルカリに提出するアウトプットと重なるようなことはできるだけ書かないようにしているが,書いたらまずそうな内容があったらTwitter( @_6v_ )などで指摘してほしい. この日記は,時系列で書いたため起伏がなくなってしまったが,アメリカに来た気分になって読んで頂けるとありがたい.

渡航

渡航前にしかできないことはいろいろあるので,少し準備していった.細かいことはいいからアメリカの写真を見せろ,という方は「日記」の章まで読み飛ばしてほしい.

ペアを組んだ

僕は早稲田大学3年の学生(以下,相方)とペアになった.相方はサークルをいろいろ立ち上げていたり,政治経済に詳しかったりで,いろいろ話を聞けたので楽しかった. (相方がオラオラ系とかウェイ系でなくて気持ち的に助かったし,高校の部活が同じとか結構共通点もあって盛り上がった.)

僕はエンジニア枠で通ったが,アイディアを考えるのにエンジニアのアドバンテージってあるのか?と少し思った.エンジニア視点からの実現可能性を含めて考えさせるためか,エンジニア学生採用のためか,新サービスのプロトタイプを期待しているのか,よく分からない.よく分からないが,結果的に僕は英語力とレポート執筆力でかなり貢献できた.何もエンジニアリングしていないのは許してほしい.

コロラド州に行くことになった

説明会で紙が配られ,コロラド州に決まった.うっわ,名前的に田舎じゃん!と思って,説明会で偶然再会した高校の友人がイギリスに行くことになったのを羨ましく思った. コロラド州の良いところを探そうとして,コロラド州についてちょっと調べたところこんな感じだった. f:id:shiba6v:20171212194358j:plain

  • ロッキー山脈の近くで,標高は1600メートルあり寒い
  • 中継ぎ空港があるので,成田から便がたくさん出ていて楽そう
  • 銃は免許制らしく,銃規制が行われているが,最近銃乱射事件があった
  • 最近は,大麻解禁で大麻スタートアップが出てきている

うん.まあ悪くはなさそう.少なくとも畑しかないド田舎ではないからヒアリングはできる.よかった.という感想を持った.

渡航日程が11月末になった

メルカリの発表では,渡航日は11/1-1/8だった. 年末は学校が無いので行きたいという人が多かったのか,最初の発表(12月末くらいだった気がする)からちょっと伸びた.説明会が10/31だったので,準備も考えると11月中旬以降じゃないと無理だった.

僕が実際に行ったのは,11/29-12/6になった.最初は年末に行きたかったが,相方と予定が合わなかったのでこの日程にした.僕が所属するのは留年率の高い電気電子工学科で,実験を欠席するのは苦渋の決断だった.しかし,事前に相談しておいたおかげで先生の理解を得られたため,いろいろと配慮してもらえた.レポートは空港の待ち時間で書いてPDFで出したし,今も遅れた分を取り返すために実験のレポートを書いている.

11月末の日程で行くのは不本意だったが,今思い返せば結果としては年末に行かなくてよかった.年末だったらおそらく大学でのヒアリングはできなかっただろう.

事前に準備した

事前に2人でこれくらいの準備をしていった.

  • 日本グッズの購入 (5000円分)
  • 日本のお菓子の購入 (5000円分)
  • 計画はざっくりとだけ立てた
  • 宿泊予定のAirbnbの宿の準備
  • デンバーの人に聞きたいことをまとめる
  • 日本のメルカリユーザーにヒアリング

f:id:shiba6v:20171212194213j:plain

事前にヒアリングのお礼として渡すために,日本グッズとお菓子を買っていった.アマゾンギフト券も買っていくことを考えたが,1枚あたり高いこと,それを使うほど長くヒアリングしないだろうこと,必要なら現地で買うのが良いことを踏まえてやめた.

ヒアリングのお礼に関して渡航後に振り返ると,日本のお菓子が半分くらい,日本グッズは数点だけ使い,アマゾンギフト券は使わなかった.アマゾンギフト券を使うような長いヒアリングはしなかったし,ミニマリスト的な考え方の人が多いのか形として残る日本グッズはあまり人気がなかった.

お菓子の中では,抹茶のキットカットが非常に人気があった.アメリカでは赤と黒キットカットしか売っていないし,キットカットなのでよく分からないものは入っていないという安心感があったのかもしれない.

行動計画については,細かく決めようがないのでざっくりと決めた. メルカリが広まったのは若い女性からだったということを考えて,事前に日本の若い女性にヒアリングするということにしたが,数少ない女性のお友達に話しかけるのをビビってほぼ聞けず,ポンコツ具合を発揮した.相方とのミーティングはたぶん4回ぐらいした.

そんなこんなで,レポート,就職面接,学祭とMashup Awardsへ向けての「猫になる」VRの準備と展示をやっていたら気が付くと渡航日だった.

日記

期間は8日間で,出国日と帰国日(時差の関係で帰国には2日かかる)を除いた5日間が活動日だった.

出国日

新幹線で成田空港まで行き,デンバー国際空港への直行便に乗る. f:id:shiba6v:20171212190046j:plain

空港に到着.空気が薄くて息を吸っても吸い足りない. f:id:shiba6v:20171212190236j:plain

滞在中はレンタカーをずっと借りる予定でいたが,窓口で聞いてみるとどこも25歳以下に対して追加料金がほぼ2倍かかるらしい.

メルカリからレンタカー乗るならめっちゃ気をつけてとアナウンスがあり,可能な限り安全に行こうと思ったことや, ロッキーマウンテン国立公園に行くつもりだったが,途中の道が冬は閉ざされていることが分かったこともあり,レンタカーを断念.ケチったわけではない.

到着してすぐに計画を変更し,2時間ほど空港で右往左往.

まあなんとかなるだろうとのことで,電車でデンバー市内へ移動. f:id:shiba6v:20171212190513j:plain

その後はバスに乗った. 僕らはどうやってバスを降りるかを知らずに必死に停車ボタンを探していたが,運転手に聞いたら教えてくれた. バスを止めたい時は,黄色い紐を引くらしい.ちまちましたボタンなんて押してられるかという心意気を感じた. f:id:shiba6v:20171212190808j:plain

宿泊はAirbnbを使ってね,とのお達しで事前に予約した宿へ.宿は結局滞在中に2軒利用した. 毎日宿を変える案もあったが,荷物の持ち運びが大変だということと,毎日宿が変わるとさらに疲れるということがあり,結果的には欲張らずに2件まで絞って正解だった気がする.

こちらが宿である.広すぎ.巨人の家かよ.

f:id:shiba6v:20171212190956j:plain

お腹が空いたのでスーパーへ.エナジードリンクがとにかく沢山置いてあった.今までは,アメリカのニュースで「エナジードリンクを2本飲んで死亡」というのを見て2本程度で死ぬわけないと思っていたが,これは2本飲んだら死ぬと思った. f:id:shiba6v:20171212195017j:plain

僕は料理が下手で,「お前よくその飯食えるな」と言われることがある程だが,相方は僕よりさらに料理ができないらしく,僕が料理した.

肉を焼き,パンと野菜を切って,雰囲気アメリカっぽい飯を作った.

お味の方は,相方「アメリカの飯は体に合わない…日本のみんなに会いたい…」と大好評(?)だった.

f:id:shiba6v:20171212194924j:plain

三階建の部屋で,屋上にはHotTabがある.HotTabとは,庭や屋上などに置くデカい浴槽である. そう,このHotTab目当てにこの宿を選んだのである.

HotTub最高!! 2時間くらい出たり入ったりしていたが,次の日の計画を立てたい相方を待たせていて申し訳ない気持ちになった.

f:id:shiba6v:20171212193417j:plain

1日目

朝寝坊し,スーパーで朝飯のベーグルを買った.相方はベーグルが硬くて大きすぎて困っていたが,デブい飯が好きな僕は2つ食べた.

事前に決めてきた質問事項をまずぶつけるために,コロラド大学に聞き込みに行った. 話しかけたらなんとかなるもので,相方の愛想が良いこともあり割と快く答えてくれる.回答率は80%くらいの感じ. (僕は普段,胡散臭いとか怪しいとか言われるので,愛想が良いのは正直羨ましい.) f:id:shiba6v:20171212200105j:plain

役割分担は,初めてのヒアリングで自然に決まった. 相方は話しかけて質問し,最高の愛想の良さと笑顔で場をつなぐ. 僕は質問への回答を聞いてメモを取り,追加で疑問点があれば質問してメモを取る. まあ我ながらいいコンビネーションだと思った.

f:id:shiba6v:20171212195854j:plain

相方「服ってどこに売る?」
デンバーの学生「売らないよ」
僕「じゃあ使い終わった服どうしてる?」
デンバーの学生「あー寄付するよ」
相方「なるほどー!」
僕「どこに寄付するの?」
デンバーの学生「Goodwillに寄付するよ」
僕「ぐっどうぃる?」
デンバーの学生「GoodWill」

といった感じで,Goodwillが何なのか気になりGoodwillへ. (2人ともGoodwillの発音が悪すぎてあまり聞き取ってくれなかったことにこの後も苦しめられた)

Goodwillは,不用品を寄付として集め,安く売ることで生活が苦しい人の暮らしを助けている.他には貧しい人を雇用したり,売り上げを慈善活動に使ったりしているらしい. f:id:shiba6v:20171212200624j:plain

この服は2ドル(200円).安すぎる. f:id:shiba6v:20171212200404j:plain

PC用カバンは後日お土産を詰めるために買った.陳列は,商品なのか分からないほど雑. 値段が書いておらず,レジに持っていったら「500万ドルね!!ハッハッハ!!」と言われたが,5ドル(500円)で売ってくれた. f:id:shiba6v:20171212200601j:plain

その後,晩飯を食べるために,多少高いが寿司レストランへ.1日目にしてもう日本食が恋しくなってしまった. メルカリからは報酬として12万円出ているので,多少高くつく選択肢も思い切って選びやすくて良かった. f:id:shiba6v:20171212202025j:plain

僕はアメイジングロール(1200円)という料理を頼んだ.サーモンとマグロとハマチの寿司(もちろん海苔は内巻き)に,ホタテと刻みわさびが乗っていた.日本の寿司とそれほど変わらない味だったので少し落ち着いた. f:id:shiba6v:20171212201035j:plain

LEDの装飾がわさびで固定されているのは斜め上の発想だった.

f:id:shiba6v:20171212200924j:plain

店員がデンバーに10年在住の日本人で,何でも聞いてね,と携帯番号を教えてもらった.

2日目

この日はさらに寝坊した.僕は,昨日スーパーで買ったチーズとナッツの塊をパンに塗って食べた.相方は,よくそれ食べられるね・・・と言ってサブウェイで朝食をとった.

コロラド大学で1日目のヒアリングの続きをした後,別のサンプルも欲しいと思い メトロポリタン・ステート・ユニバーシティー・オブ・デンバー (以下,MSU)に行った. 訳すと首都州立大学デンバーになって首都大学東京っぽい名前だと思いつつ,聞き込みをしていった. f:id:shiba6v:20171212202500j:plain

MSUでは,ビリヤードなどで遊んでいる人が多く話しかけづらかったためコロラド大学へ戻った.

コロラド大学とMSUは非常に近い場所にある大学ではあるが,カラーが違った.コロラド大学は,National Universityという種類の大学で,世界から学生が集まり,博士課程までの教育を行う.MSUはRegional Universityという種類の大学で,地域の住民を中心に学士課程,修士課程の教育を行う大学らしい.日本で言うところのL型大学G型大学の話に近いのかなと思った.

アメリカはクレジットカードで決済を行うのが普通で,この滞在中には僕は現金を一切使わずクレジットカードだけで生活できた.自動販売機すらクレジットカード対応なのはとても驚いた. そうなると,怪しい自動販売機にクレジットカードが吸い込まれていくことは無いのかと思ったが,日本のように道端にたくさん自動販売機があるわけではないのでそのような問題は起きないことに気がついた.

f:id:shiba6v:20171212202630j:plain

昼過ぎは,昨日作った新たな角度からの調査項目に関してヒアリングをした.相方はお疲れの模様.そりゃそうだ.

夜にはピザを頼んだ.日本のピザのLサイズは直径36cmだが,これは50cm.これだけ大きくても,ハーフアンドハーフのようなみみっちいことはしないのだ.

チーズとマカロニの相性は最高だったが,これはデカすぎてさすがに残した.残した分は朝ごはんになった.相方が頼んだレモネードは日本のレモネードとは違って炭酸が入っていない優しい味だった.実際に見たわけではないが,アメリカで子供がレモネードスタンドで売っている光景が目に浮かんだ. f:id:shiba6v:20171212203016j:plain

3日目

3日目は気分転換のために観光の日にした.コロラドスプリングスに行くために,レンタカーを借りた.もちろん左ハンドルである. 僕の運転は,日本にいる時には「怖すぎて死ぬかと思った!運転やめろ!」とよく褒められるので,運転が好きだという相方に全部任せた.ありがたい. f:id:shiba6v:20171212203943j:plain

ロッキー山脈のパイクスピーク東のふもとの町,コロラドスプリングスに行き,ガーデンオブゴッズという観光地を見た.敷地内に駐車場がたくさんあるので,どれかに停めて歩いて回るという感じだった.入場は無料で,アメリカの懐の深さを感じた.

f:id:shiba6v:20171212204406j:plain

感想としては,とにかく岩がデカい.最近遊んだゼルダの伝説BoWで見た崖を思い出した.ロッククライミングをしている人もいて,より一層ゼルダの伝説BoWを思い出した.小さい頃からこういった景色を見て,大自然に触れて暮らせるコロラド州の子供が羨ましくなった.

f:id:shiba6v:20171212204735j:plain

3日目には全く関係ないが,1日目に空港の近くで見かけた銅像ゼルダの伝説BoWにあったものに非常に似ていたので驚いたことを思い出した. f:id:shiba6v:20171212224417j:plain

他に気づいたこととして,観光道でもスーパーでもそうだが,すべての道は車椅子の人にも通れる広さになっている.道が広いため,人と人がぶつかることは無いし,車が横断歩道前でギリギリまで人に近づくようなことも無い.

これは,バランスロックという崩れそうで崩れない岩.岩の塊と地面の接続部分は硬い地層になっていて,そうでない部分は触るとポロポロと崩れそうな部分もあった.

f:id:shiba6v:20171212205139j:plain

帰りにオールドコロラドシティというゴールドラッシュの時代に栄えたという町に寄り,昼食を食べた.

僕はアメリカで大きなハンバーガーを食べるのが夢だったので,迷わずハンバーガーを注文.店員に「〜〜〜?ポテトのせる?〜〜〜?」と聞かれてよく分からなかったのでYESと答えたらこれが出てきた.いやポテト乗せるのそこかい,とツッコんでしまった.

コショウが効きすぎでキツかったけど,食べ応えバツグンで美味しかった.

f:id:shiba6v:20171212210414j:plain

寿司レストランで会った日本人が,明日クリスマスパレードがあると言っていたことを思い出し,デンバーに戻ってレンタカーを返してから行くことにした. レンタカーを返そうとしたものの,営業時間外に鍵を返却する方法が分からず,とりあえず駐車場に車を置いてパレードに行った.かなり混んでいたが,見れてよかった.

f:id:shiba6v:20171212210816j:plain

マーチングバンドや踊りなど色々な行進があった.その中で,LEDで装飾したパトカーと救急車がサイレンを鳴らしたり停めたりして行進していたのがとても気に入った.これは日本でやったら苦情が来そうなクールさだと思った.

f:id:shiba6v:20171212211018j:plain

帰りはバスがマップ通りでなく,乗れそうになかったため,Uberを召喚した.

召喚!!!来いUber!!!

f:id:shiba6v:20171212211034j:plain

しかし,渋滞のせいで20分ほど待ってもほぼ動かず,これに乗っても帰れそうにないので召喚をキャンセルした.

その後もバスを探して歩き回ったが,結局,歩いて帰宅した.この日は2万歩歩いた.写真は一般道の高速レーンで,有料で専用レーンを通れるというものだが,これは車のナンバープレートをカメラが読み取って請求するらしい.ETCはなかった.

f:id:shiba6v:20171212211830j:plain

この日から別のAirbnbの宿に泊まることにしたが,鍵ボックスがあるタイプでなくホストに電話してロック番号を教えてもらう方式だった.電話をする際にSIMカードが必要だったので,ポケットWi-FiでなくSIMカードを持ってきて本当に良かったと思った.下手すると0℃近い外気温の中,野宿をしていたかもしれない.

f:id:shiba6v:20171212211705j:plain

4日目

レンタカーの鍵を返しに行く必要があったため,朝早く起きてデンバーに向かった.鍵を返却する場所を探した.どこに返せばいいのか・・・?

f:id:shiba6v:20171212212540j:plain

これかーい!!
返却の際は手続きは必要なく,鍵ボックスもただの引き出しで,不安になって店員に聞いてみたがこれに鍵を入れるだけで良いらしい.

昼食は,YelpやGoogle Mapで評価の高いNick's Dinerに行き,オムレツを頼んだ.中に入っている肉の味が濃くてとても美味しかった.

f:id:shiba6v:20171212213154j:plain

道を歩いていると,道端によく新聞が捨てられているのを見かけたが,これは捨てられているのではなく配達されているらしい.

f:id:shiba6v:20171212213625j:plain

この荷物もどうやら配達されているらしい.捨てられているようにしか見えない・・・

f:id:shiba6v:20171212213649j:plain

この日は,ヒアリング結果をまとめた.そうするうちに,デンバーの人の物の売買に対する課題がだいたい分かってきた.メルカリが新しく作るべきサービス案を作成し,次の日のヒアリングで新サービスに関する意見をもらうという予定を立てた.

夕食にはUber EATSでメキシコ料理をデリバリーした.タコスは外がサクサクでとても美味しかった. f:id:shiba6v:20171212214036j:plain

5日目

この日はコロラド大学に行き,新サービス案をぶつけて検証した. 疲れている相方に,まだ検証したいというワガママを聞いてもらって新サービスに対する意見をもらった.多少修正するべき部分もあったが,全体的には「それはとても便利だと思う!」という感じで好評だった. 大学で買って飲んだモンスターは炭酸が入っておらずスルスルと飲めてしまって怖かった.

f:id:shiba6v:20171212214554j:plain

この日もデンバー市内のお店を回って,どこから商品が来て誰に売るのかといったことを調査した.日本から来た学生だと言うといろいろ教えてくれるので,学生はとても良い身分だと思った.

出発日

帰る時に,駅でサンドイッチを食べた.半分でも満足できる量だが,ハムが大量に入っているので日本のコンビニのサンドイッチには見習ってほしい.

f:id:shiba6v:20171212215012j:plain

最後に

アメリカで行った場所や食べたもの,見たこと聞いたこと,それについて感じたことについて漫然と書いたが,このインターンに参加することができてとても良かったと思う.

ただ海外旅行をして観光地を見るのに比べると非常に多く現地の人の話を聞く機会があり,文化の違いに触れることができた.実際に行くまでは,ここまでアメリカの人の売り買い文化について理解が深まるとは思っていなかったので,とても満足だった.

最初はメルカリに提出するアウトプットの内容の見当も付かなかったが,行ってみると現地の人が抱えている売買に対する課題がたくさん見つかり,新規サービス案を考えることができた.

また,日本から世界へ向けてプロダクトを広げていくメルカリは本当にステキだと思った.世界の様子の現地調査をするのに学生をインターン生として雇うのもステキで,このインターンに来た学生がアメリカを見ることで日本に留まらない視点を持って,それがいずれ何らかの形で日本に還元されていくと思った.

他の企業でも,世界に向けてプロダクトを出している企業はステキだと思うので,その際の世界に向けた目と耳の役割を少しでも学生にインターンという形でやらせてもらえると,10年後20年後,面白いサービスが日本から世界に向けて沢山出てくるような気がする.

おしまい!

次回,CAMPHOR- Advent Calendar 2017 14日目は @marty1martie の担当です.