エイバースの中の人

アプリとWEBサービスを作っているABARSのBLOGです。

tf2onnxのTransposeの抑制

tf2onnxでONNXに書き出すと、大量のTransposeが生成されます。これは、TensorflowがNHWCなのに対して、ONNXがNCHWなため、並べ替えが発生するためです。この問題は、TransposeOptimizerを使用することで回避することができます。

通常のエクスポートコード
    graph1 = tf.Graph()
    with graph1.as_default():
        tf.import_graph_def(frozen_graph_def)
        onnx_graph = tf2onnx.tfonnx.process_tf_graph(graph1, input_names=input_names, output_names=output_names, opset=10)

        model_proto = onnx_graph.make_model("onnx")
        with open("output.onnx", "wb") as f:
            f.write(model_proto.SerializeToString())

before

TransposeOptimizerを使用
    graph1 = tf.Graph()
    with graph1.as_default():
        tf.import_graph_def(frozen_graph_def)
        onnx_graph = tf2onnx.tfonnx.process_tf_graph(graph1, input_names=input_names, output_names=output_names, opset=10)

        from tf2onnx.optimizer.transpose_optimizer import TransposeOptimizer
        optimizer = TransposeOptimizer()
        opt_model_proto = optimizer.optimize(onnx_graph)

        model_proto = onnx_graph.make_model("onnx")
        with open("output.onnx", "wb") as f:
            f.write(model_proto.SerializeToString())

after

オプティマイズすることで、推論速度は1.5倍程度高速化されます。

tf-onnx introducing many transpose operations
add transpose optimizer, and integrate it after tf graph conversion #108

2019年の投資戦略

2017年〜2018年は割安株が少なくなっていたため、小型のバリュー株に投資しつつ、あまり大きなポジションは持っていませんでした。しかし、2019年に入って、株価の二極化が進み、割安な株が増えてきたためポジションを増やしています。

具体的には、銀行、電力、不動産、化学の分野で配当利回り4〜5%でPER10倍以下、PBR1倍以下の大型株を中心に分散したポートフォリオを作っています。従来は小型株への集中投資派だったのですが、ここまで大型株の株価が下がると、あえて流動性の低い小型株に投資する妙味が減っているように思います。

最近はコーポレートガバナンス・コードの圧力もあり、戦略的な投資を行う強い大企業が出てきている印象があります。小型のバリュー株におけるカタリストという観点だと、製販一体化のためのM&Aや、成熟市場の寡占化のためのM&A、親子上場解消のためのM&Aなどを狙うことになると思います。ただ、小型のバリュー株は流動性の問題が大きいので、こちらもできるだけ分散して持っておくことが重要かなと思います。2018年までの高値は、流動性が低い中での株式投資ブームとSNSの活用に伴うイナゴ化による上昇の影響が大きい気がしていて、現状の株式市場の新規参入が少ない中では、分散しておいて安定配当をもらいながら、カタリストの到来を待つ、という方がよいかなと思います。

不動産の領域では、国内のマネタリーベースが順調に拡大しており、日銀のバランスシートの肥大化が止まらないので、日本銀行券の価値は落ちる方向と考えていて、直近のREITの高騰はその先取りかなと考えています。それに比べると、国内の不動産株は含み資産が多く、REITを買うよりも国内の不動産株の方が魅力的かなと思います。



銀行株は、単純に2016年水準まで落ちてきており、地銀だとPER3、PBR0.5とか、全く評価されていない水準になっているので買っています。米中貿易戦争に伴い、もう一回、東京がアジアの金融センターになるかもという期待もあります。

電力株は、現在は無配ですが、将来的にはどれも50円配当まで戻るのではと考えて、先行して買っています。電力も自由化で合併が進むような気がしていて、北陸電力は中部電力からのM&A期待です。

気持ち的には、資産が国内に偏っているので、海外株などにも手を出したいとは思っているのですが、米国株よりも国内株の方が今後のパフォーマンスが良い気がしていて、まずは国内株中心に投資しようと思います。



ちなみに、現在のポジション一覧は下記になっています。これだけ大量に分散したのは初めてです。

8354 ふくおか
9513 Jパワー
8801 三井不
7911 凸版印
3106 クラボウ
7272 ヤマハ発 
1515 日鉄鉱
3892 岡山製紙
9505 北陸電力
3407 旭化成
7242 KYB
9511 沖縄電力
5938 LIXIL G
4676 フジHD
9401 TBSHD
4401 ADEKA
5411 JFE
1376 カネコ種苗
9507 四国電力
5979 カネソウ
9302 三井倉HD
8418 山口FG
8316 三井住友
6486 イーグル工
6178 日本郵政
9324 安田倉
9501 東電力HD
9509 北海電力
3048 ビックカメラ
9502 中部電力
8306 三菱UFJ
9831 ヤマダ電機
3222 U.S.M.H
8385 伊予銀
4517 ビオフェルミン
7201 日産自
4188 三菱ケミHD
9409 テレビ朝日HD
8864 空港施設
3895 ハビックス
6301 コマツ
7945 コマニー
2193 COOKPAD 
2329 東北新社
2674 ハードオフ
9405 朝日放送グループHD
7902 ソノコム
7552 ハピネット
3284 フージャース
7544 スリーエフ 
9055 アルプス物
7399 ナンシン
1514 住石HD
4364 マナック
9193 東京船
9414 日本BS放送
5973 トーアミ
9428 クロップス
6797 名古屋電
7891 日本ユピカ
9404 日テレHD
3954 PAXXS
7950 デコラックス
9402 中日放送 
9036 東部ネット
2914 JT 
3436 SUMCO
8818 京阪神ビ
8251 パルコ
3791 IGポート
9278 ブックオフGHD
8591 オリックス
7561 ハークスレイ
8308 りそなHD
9468 KADOKAWA
2329 東北新社

ChainerのDeeplanv3の入出力解像度の調査

サンプル:examples/deeplab
モデル:chainercv/links/model/deeplab

学習に使用したデータセットによって入力解像度が異なる。入力解像度未満の画像は入力解像度まで引き上げられる。

cityscapes : 1025x2049
ada20k : 513x513
voc : 513x513

入力画像のレンジは-1.0〜1.0。

Deeplabv3のFeatureExtractorは下記の解像度を出力する。

voc : 21x129x129

21はカテゴリ数である。各画素はカテゴリ数分のスケールがかかっているため、/21を行う。

セグメンテーションを可視化する際にはバイリニアで元解像度まで拡大した後、しきい値処理する。

vis_semantic_segmentation.py

PytorchからONNXを書き出す際のワークアラウンド

1. RuntimeError: Only tuples, lists and Variables supported as JIT inputs, but got collections.OrderedDictが発生する

deeplabv3などでは以下のようにOrderedDictに値を代入して返していますが、ONNXエクスポータが扱うことができません。

result = OrderedDict()
x = features["out"]
x = self.classifier(x)
x = F.interpolate(x, size=input_shape, mode='bilinear')
result["out"] = x
return result

そのようなケースでは、下記のように書き換えます。

x = features["out"]
x = self.classifier(x)
x = F.interpolate(x, size=input_shape, mode='bilinear')
return x

RuntimeError: Only tuples, lists and Variables supported as JIT inputs, but got dict #13040

2. KeyError: 'upsample_bilinear2d'が発生する

ONNXのエクスポータにバイリニアが定義されていないため、エラーになります。

x = F.interpolate(x, size=input_shape, mode='bilinear')

nearestに置き換えるか、/usr/local/lib/python3.7/site-packages/torch/onnx/symbolic_opset10.pyに下記を追加します。

upsample_bilinear1d = _interpolate('upsample_bilinear1d', 3, "linear")
upsample_bilinear2d = _interpolate('upsample_bilinear2d', 4, "linear")
upsample_bilinear3d = _interpolate('upsample_bilinear3d', 5, "linear")

upsample_bilinear2d issue when exporting to onnx #22906

PytorchからONNXへの変換時にtrack_running_statsの未定義エラーが発生

PytorchからONNXへの変換時に、Pytorch0.3系で学習したモデルの場合、BatchNorm2dもしくはInstanceNorm2dにおいて
 object has no attribute ‘track_running_stats’
というエラーが発生します。

この問題を解決するには、BatchNorm2dもしくはInstanceNorm2dを探索し、track_running_statsに値を設定します。

def recursion_change_bn(module):
    if isinstance(module, torch.nn.BatchNorm2d) or isinstance(module, torch.nn.InstanceNorm2d):
        module.track_running_stats = 1
    else:
        for i, (name, module1) in enumerate(module._modules.items()):
            module1 = recursion_change_bn(module1)
    return module

for i, (name, module) in enumerate(model._modules.items()):
    module = recursion_change_bn(model)
model.eval()

上記対処をすると、ONNXへの書き出しに成功します。

x = Variable(torch.randn(1, 3, 64, 64))
torch.onnx.export(model, x, 'output.onnx', verbose=True)

参考:‘BatchNorm2d’ object has no attribute ‘track_running_stats’

第30回IGポート株主総会レポート(2019/08/27)

2019年のIGポート株主総会レポートです。

IMG_0848

場所:三鷹産業プラザ
参加者:90名程度

最初に京アニへのお悔やみの言葉があった後、今期の報告がありました。営業制作事業がコスト増による赤字との説明。その後、来期の計画の説明。グローバルな事業展開が進む中、子会社の役員は子会社の専念する体制を作るとともに、新たにCEOとCOOを置く経営体制になる。また、NTTぷららの坂東さんが社外役員に就任されるとのことです。以下、質疑応答です。

魔法使いの嫁は100%権利を持っているが、無料公開して販促に活用するようなことはできるか


魔法使いの嫁は原作権を持っているが、60%の権利になっている。現在、有料配信しており、ビジネス上の判断から無料公開は行わない。

コスト削減施策は一時的なものと永続的なものがあるが、来期の映像制作のコスト削減施策はどれくらいの比率か


来季は粗利率の改善を見込む。戦略作品は原価が上がる傾向がある。総合的に、粗利が上がるような施策を行っていく。

サイコパスの舞台には出資しているか


次の舞台は製作委員会を組成中。

対処すべき課題の映像制作の高度化に関して取り組んでいることは何か


シグナルMD含めて、紙からのデジタル化を推進している。タブレットで描く。また、サーバやインフラの整備を行っており、Nスタジオで技術開発を行っている。現在はトライアルで短い作品をやっている。とつくにの少女はフルデジタル。サイコパスはアナログとデジタルの融合。IGの強みを活かしていく。

XEBECの売却の理由は何か


利益剰余金が減る一方で、この先、さらに現象が進むと判断して、最悪のパターンになる前に手を打とうとしたが、うまく改善できなかったので、最終的に売却した。苦渋の選択ではある。サンライズさんは通常はアニメーターを正社員として雇うことはないが、交渉の中で正社員として受けていただいた。映像の権利はIGが保有している。ファフナーは今後も作っていく。

取締役の人数が減っている。利益なき繁忙ではないか。子会社の何がうまくいっていないか。


IGグループ一丸となって良い作品を作ってきたが、自分たちの身の丈にあった制作環境になっていなかった。毎月、仕掛かりについて周知徹底する会議を開く。スタジオとして強くしていく。また、第四の柱としてディジタルメディア事業を考えている。坂東さんの招聘はそのため。NTTぷららで増収増益を行ってきた手腕を発揮していただきたい。

クラウドファンディングは検討しているか。


クラウドファンディングに限らずフィンテックの活用を検討していく。

ドル円による影響は。


110円を想定している。海外はIG USAが窓口。アビアラッドが会長をしており、海外展開を推進していく。

ネットフリックスとの提携による影響は。


現在、ビデオグラムのみではコストが合わなくなってきている。ネットフリックスとの提携はプラス。

アクティビストファンドが購入しているが接触は。


機関投資家との1on1ミーティングをやっている。そこで評価されたのではないか。現状は株主提案はない。

ナデシコの権利は?


IGにある。

その後、決議を行い、坂東さんの挨拶。23年前、NTTぷららの社長になった。2008年からは光TVを一生懸命やった。この10年で日本を代表するサービスになった。このノウハウ、IP化がお役に立てると考えている。全力で経営に当たりたい。

11:00開始で12:00に終了しました。

昔は映像制作が黒字、出版が赤字だったのですが、最近は映像制作が赤字、出版が黒字と逆転しており、ポートフォリオを持った経営が重要だと思いました。今期から役員体制が刷新され、特にNTTぷららを退任された坂東さんが社外役員に入るということは驚きでした。ビデオグラム中心から映像配信中心へのシフトという中、IPを軸にどのような事業展開を行っていくのかに注目しています。

TensorflowからONNXへのエクスポート

TensorflowからONNXにエクスポートするには、tf2onnxを使用します。

インストール
pip3 install tf2onnx

まず、tf.graph_util.convert_variables_to_constantsを実行することで、Tensorflowのgraphのvariableをconstantに変換しておきます。これをfrozenと呼びます。

ただし、convert_variables_to_constantsにはBatchNormalizationでmoving_varianceのvariableをfrozenできない問題があるため、事前に問題の起こるノードを修正しておきます。(Unable to import frozen graph with batchnorm

# fix batch norm nodes
gd = sess.graph.as_graph_def()
for node in gd.node:
    if node.op == 'RefSwitch':
        node.op = 'Switch'
        for index in range(len(node.input)):
            if 'moving_' in node.input[index]:
                node.input[index] = node.input[index] + '/read'
   elif node.op == 'AssignSub':
        node.op = 'Sub'
        if 'use_locking' in node.attr: del node.attr['use_locking']

# Freeze the graph
output_node_names=["upscale/mul","hourglass/hg_2/after/hmap/conv/BiasAdd","radius/out/fc/BiasAdd"]
frozen_graph_def = tf.graph_util.convert_variables_to_constants(
    sess,
    gd,
    output_node_names
)

次に、tf2onnx.tfonnx.process_tf_graphを実行することで、ONNXに変換します。引数には入力と出力に対応するノードを指定します。

# Convert to onnx
input_names=["import/eye:0"]
output_names=["import/upscale/mul:0","import/hourglass/hg_2/after/hmap/conv/BiasAdd:0","import/radius/out/fc/BiasAdd:0"]
graph1 = tf.Graph()
with graph1.as_default():
    tf.import_graph_def(frozen_graph_def)
    onnx_graph = tf2onnx.tfonnx.process_tf_graph(graph1, input_names=input_names, output_names=output_names)
    model_proto = onnx_graph.make_model("sample")
    with open("sample.onnx", "wb") as f:
        f.write(model_proto.SerializeToString())

出力されたONNXが正しいかどうかを、ONNXRuntimeを使用して検証します。

# Inference
import numpy
import onnxruntime as rt
onnx_sess = rt.InferenceSession("sample.onnx")
for node in onnx_sess.get_inputs():
    print(node.name)
    print(node.shape)
    print(node.type)
X = numpy.random.random((2, 36, 60, 1)).astype(numpy.float32)
pred_onnx = onnx_sess.run(None, {"import/eye:0":X})
print(pred_onnx)

なお、Placeholderがtf.contrib.layers.batch_normのis_trainingに接続されているなどすると、Ifを含むONNXが出力されるため、必要に応じてFalseなどの直値を設定しておきます。

adbでdevice unauthorizedになる問題の対処方法

Macのadbでadb devicesをしてもunauthorizedになる問題の対処方法です。この状態だと、adb logcatが使えません。

Macのadbでは、~/.android/にあるキーファイルと、Androidのdata/misc/adb/adb_key/にあるキーファイルで認証を行なっています。~/.android/にキーファイルが存在する場合、AndroidのUSBデバッグの設定で、”USBデバッグ認証を無効にする”を実行することで、接続できるようになるそうです。

しかし、何らかの原因で~/.android/にあるキーファイルが失われると、unauthorizedのまま復帰できなくなります。

このような場合、adb接続できる別のMacを用意し、~/.android/フォルダのadbkeyとadbkey.pubを、問題の起きているMacにコピーします。その後、adb devicesを実行することで接続ができるようになります。

How to solve ADB device unauthorized in Android ADB host device?

SnapdragonProfilerでデバイスが見つからない

Androidのパフォーマンスプロファイラーの一つに、Qualcommの提供するSnapdragonProfilerがあります。

SnapdragonProfilerをMacから使おうとした際、adbではデバイスを認識していますが、SnapdragonProfilerからはデバイスが見つからない問題が発生しました。これは、SnapdragonProfilerがadbを認識できていないのが問題のようです。

Macでは一般に、.bash_profileにAndroidSDKのplatform-toolsのパスを通しますが、そのパスをSnapdragonProfilerが認識できないのが原因なため、Terminalからopen /Applications/SnapdragonProfiler.appとしてSnapdragonProfilerを起動すると認識できるようになります。

Forums - Snapdragon Profiler can not find device in Mac

なお、Profilerにかけるには、apkのdebugging attributeをONにする必要があるため、UnityではDevelopmentBuildに指定する必要があります。

TensorFlow Graphicsによる3DメッシュへのCNNの適用

TensorFlow Graphicsは3Dメッシュに対してCNNを適用できるようにするフレームワークです。従来、TensorFlowで3Dメッシュを扱う場合は、ボクセルに変換して扱っていました。TensorFlow Graphicsでは、新たに、微分可能レンダラと、メッシュに対するGraph Convolutionを実装することで、3Dメッシュをそのまま扱えるようにしています。mesh_segmentationによる3Dメッシュの各ポリゴンへのラベリングなど、今までできなかった処理が可能になります。

従来のコンボリューションは2D画像に対して適用していました。

cat_image_convolutions

グラフコンボリューションでは、3Dメッシュの頂点に連結している頂点に対して重みをかけて畳み込みを行います。畳み込みを行うと、チャンネル方向に3Dメッシュが増殖していくイメージになります。

cat_mesh_convolutions

グラフコンボリューションによって、3Dメッシュの部位ラベルの付与が可能になります。

mesh_segmentation

頂点と頂点の接続関係はマトリックスで定義します。頂点iと頂点jが接続されている場合、A[i,j]に値が入ります。性質上、対角には必ず値が入ります。

A[i, j] = w[i,j] if vertex i and vertex j share an edge,
A[i, i] = w[i,i] for each vertex i,
A[i, j] = 0 otherwise.
where, w[i, j] = 1/(degree(vertex i)), and sum(j)(w[i,j]) = 1

モデルデータは、頂点列とポリゴンを構成する頂点ID、頂点の接続情報から構成され、tfrecordsに格納されます。fbxなどからの変換ツールはまだリリースされていません。(3D format to .tfrecords

それでは、MacにTensorFlow Graphicsをインストールしてみます。

TensorFlow Graphicsをインストールします。

pip3 install tensorflow-graphics

Jupyter Notebookをインストールします。

pip3 install jupyter

Colabtoolsをインストールします。

git clone https://github.com/googlecolab/colabtools.git
cd colabtools
python setup.py install

Colabtoolsをインストールしていない場合は、threejsを使ったモデルビューワで下記のエラーが発生します。

---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
 in 
     19     'vertex_colors': mesh_viewer.SEGMENTATION_COLORMAP[test_labels[0, ...]],
     20 }
---> 21 input_viewer = mesh_viewer.Viewer(input_mesh_data)

/usr/local/lib/python3.7/site-packages/tensorflow_graphics/notebooks/mesh_viewer.py in __init__(self, source_mesh_data)
     56 
     57   def __init__(self, source_mesh_data):
---> 58     context = threejs_visualization.build_context()
     59     self.context = context
     60     light1 = context.THREE.PointLight.new_object(0x808080)

/usr/local/lib/python3.7/site-packages/tensorflow_graphics/notebooks/threejs_visualization.py in build_context()
     72   """Builds a javascript context."""
     73   threejs_url = 'https://www.gstatic.com/external_hosted/threejs-r98/'
---> 74   _publish.javascript(url=threejs_url + 'three.min.js')
     75   _publish.javascript(url=threejs_url + 'examples/js/controls/OrbitControls.js')
     76   return _js_builder.Js(mode=_js_builder.PERSISTENT)

NameError: name '_publish' is not defined

サンプルをcloneします。

git clone https://github.com/tensorflow/graphics.git

サンプルを実行します。

cd tensorflow_graphics
cd notebooks
jupyer notebook

notebooks/mesh_segmentation_demo.ipynbがmesh_segmentationの推論サンプルです。まだ学習側のコードは公開されていませんが、ディープラーニングの応用例が3Dにまで広がっていく未来が楽しみです。

notebooks/spherical harmonics optimization.ipynbが球面調和ライティングの環境マップを計算するサンプルです。TensorFlow Graphicsに含まれる微分可能レンダラーを使用することで、与えられた画像から、環境マップテクスチャを推定します。

学習の推移です。

spherical_harmonics2

学習結果のテクスチャです。

spherical_harmonics3

TensorFlow Graphicsの概要動画です。

TensorFlow+Kerasのresize_bilinearのUpSampling2Dへの置き換え

TensorFlow+Kerasでヒートマップ系のモデルを使用する場合、レイヤーの途中で画像サイズを拡大するためにlambdaを使用したBilinearフィルタが含まれるケースがあります。lambdaを扱えないハードウェアで推論する場合、この処理を規定のレイヤーに置き換える必要があります。

up2 = Lambda(
     lambda x: tf.image.resize_bilinear(
        x[0],
         x[1].shape.as_list()[1:3], 
         align_corners=True))([low3, up1])

単純に、元画像の1/2になっている場合は、UpSampling2Dに置き換えることができます。しかし、縮小時のテンソルが奇数の場合に、丸めが行われ、UpSamping2Dではテンソルサイズが合わない場合があります。たとえば、(5,5) -> (3,3)に縮小されたテンソルだと、(3,3) -> (6,6)に拡大されてしまいます。

この場合、4倍まで出力を拡大したあと、Croppingして、縮小することでサイズをあわせることができます。

from_shape=low3.shape.as_list()[1:3]
to_shape=up1.shape.as_list()[1:3]
crop_h=from_shape[0]*2-to_shape[0]
crop_w=from_shape[1]*2-to_shape[1]
common_upsample = UpSampling2D(size=(4,4), name=prefix_name+"_up_sampling2d")(low3)
common_multiple = Cropping2D((crop_h,crop_w), name=prefix_name+"_crop")(common_upsample)
up2 = AveragePooling2D(pool_size=(2,2), strides=(2,2), padding="same", name=prefix_name+"_downsampling")(common_multiple)

keras2caffeを使う場合は、UpSampling2Dの名前はup_sampling2dをつけておきます。

これで、多様なハードウェアで動作するようなネットワークを構築することができます。なお、出力はBilinearとは異なり、NearestNeighborとなるため、完全に一致はしません。

このように変更したあとに、規定の学習済みモデルを読み込むには、load_weightsでby_name=Trueを指定します。

net.load_weights("keras.h5",by_name=True)

numpy1.15に対応するtensorflowのバージョン

numpy 1.16ではcaffeが動作しないため、numpy 1.15を使いたい場合に対応するtensorflowのバージョンは1.12のようです。

TensorFlow 1.12
scikit-learn 0.20.0
XGBoost 0.81
numpy 1.15.4

ランタイム バージョン リスト

バージョンを指定したインストールは下記のコマンドで行います。

pip install numpy==1.15
pip install tensorflow==1.12

Tensorflow、numpy、cudnn、cuda、caffeのバージョンを揃えないといけないのがとっても大変ですね。

ディープラーニングのモデルを可視化できるnetron

netronはcaffemodelやtfliteファイルのネットワーク構造を可視化できるツールです。ブラウザで動作します。

例えば、darkflowで変換したyolo_tinyを可視化すると下記のようになります。leaky reluがmulとmaxにマッピングされていることが分かります。

yolo_tiny


mobilenetだと下記のようになります。tfliteによってモデルが最適化され、レイヤーが統合されていることが分かります。

mobilenet

WindowsのPythonにdlibをインストール

WindowsのPythonにdlibをインストールする場合、Links for dlibからPythonのバージョンに対応したビルド済みバイナリのURLを取得します。

Python 3.5 + 64bitの場合、以下のコマンドでインストールすることができます。cp35がPythonのバージョン、amd64が64bitバイナリの指定です。

pip install https://files.pythonhosted.org/packages/38/18/92fc25855307bcf582a30034ae657fda205de4f29773323bb388e592f17c/dlib-19.4.0-cp35-cp35m-win_amd64.whl#sha256=67e7d86eedaef650788b058d9e086198ead583f5bb3041fd9a431ae50658e9f4

MojaveでXcodeをインストールしようとすると空き容量が足りないと言われる

MojaveでXcodeをインストールしようとすると、40GBの空き容量があるのに、空き容量が足りないと言われる問題が発生しました。

Mojaveでは1時間に1つ、TimeMachineのローカルバックアップを作成します。「このMacについて」で表示される空き容量にはこのローカルバックアップはカウントされないため、空き容量があるものの、AppStoreアプリから見たときに空き容量が不足して見えるようです。

"Not enough free space" when trying to install XCode even though there's ~7x more free space than required

このバックアップは下記コマンドで削除できます。

for d in `tmutil listlocalsnapshots / | awk -F'.' '{print $4}'`; do sudo tmutil deletelocalsnapshots $d; done


ローカルバックアップを削除すると、無事、インストールできました。

UnityのWebCamTextureのパラメータ

UnityのWebCamTextureはデバイスによって回転された画像が取得されるため、画像認識を行う際、適切に回転させる必要があります。デバイスによって取得できる値をまとめました。使用した環境はUnity5.5です。

パラメータ
パラメータ名内容
videoRotationAngle右回りの角度 (度) を返します。多角形を回転させるためにその値を使用し、カメラのコンテンツを正しい向きで表示できます。
videoVerticallyMirroredテクスチャ画像が垂直に向きをかえているかどうか。

実機での取得値
デバイスvideoRotationAnglevideoVerticallyMirrored
MacPro20130False
iPadPro 2018 Landscape Incam180True
iPadPro 2018 Landscape Outcam0True
iPadPro 2018 Portrait Incam90True
iPadPro 2018 Portrait Outcam90True
GeminiPDA Landscape Incam180False
GeminiPDA Landscape Outcam--
GalaxyS8 Portrait Incam90False
GalaxyS8 Portrait Outcam270False

コードとしては、angle=90もしくはangle=270の場合は出力のxy軸を反転、angle=90もしくはangle=180の場合は出力の垂直反転でいけるようです。

KerasでHDF5Matrixを使用して学習を高速化

小さな画像が大量にある場合、ImageDataGeneratorを使用するとディスクのランダムアクセスネックでGPU使用率が伸びず、学習速度が低下します。学習画像を事前にHDF5に書き込んでおくことで、ランダムアクセスを抑制し、高速化することができます。

まず、flow_from_directoryから取得できる学習用データからh5pyを使用してHDF5を作成します。以下の例ではtrain.h5を作成します。同様にvalidation.h5も作成します。

train_generator = train_datagen.flow_from_directory(
   INPUT_PATH+'/annotations/'+ANNOTATIONS+'/train',
   target_size=(IMAGE_SIZE, IMAGE_SIZE),
   batch_size=BATCH_SIZE,
   class_mode='categorical',
   shuffle=True
)

training_data_n = len(train_generator.filenames)
training_class_n=len(train_generator.class_indices)

import h5py
f = h5py.File("train.h5", 'w')
train_x = f.create_dataset('training_x', (training_data_n,IMAGE_SIZE,IMAGE_SIZE,3), dtype='f')
train_y = f.create_dataset('training_y', (training_data_n,training_class_n), dtype='f')

cnt=0
for x_batch, y_batch in train_generator:
  for i in range(BATCH_SIZE):
    train_x[cnt] = x_batch[i]
    train_y[cnt] = y_batch[i]
    cnt = cnt+1
    if cnt>=training_data_n:
        break
  if cnt>=training_data_n:
    break

f.close()

学習時はHDF5Matrixを使用します。

  from keras.utils.io_utils import HDF5Matrix
  x_train = HDF5Matrix("train.h5", 'training_x')
  y_train = HDF5Matrix("train.h5", 'training_y')
  x_validation = HDF5Matrix("validation.h5", 'validation_x')
  y_validation = HDF5Matrix("validation.h5", 'validation_y')
  fit = model.fit(
    epochs=EPOCS,
    x=x_train, 
    y=y_train,
    validation_data=(x_validation,y_validation),
    batch_size=BATCH_SIZE,
    shuffle='batch'
  )

VGGFace2を使用した性別推定モデル(3146003画像)では160GBのHDF5を生成し、学習時間を1EPOCで3時間から30分に削減でき、6倍高速化できました。評価環境はGeforceRTX2080、32GBメモリ、1TB SSDです。

floatではなく8bit unsigned intでhdf5ファイルに書き込むこともできるようですが、以下のコードで試してみたところ、学習がほとんど進まなくなってしまいました。

train_x = f.create_dataset('training_x', (training_data_n,IMAGE_SIZE,IMAGE_SIZE,3), dtype='uint8')
train_x[cnt] = x_batch[i].astype(np.uint8)

学習時のノーマライズは下記のように行いましたが、どこかに問題があるようです。

ds_norm = lambda x: x / 255.0
x_train = HDF5Matrix(HDF5_PATH, 'training_x', normalizer=ds_norm)

KerasでGPUのメモリ使用量を抑制する

kerasではデフォルトでGPUメモリを100%確保します。ディスクネックでGPU使用率が低く、複数の学習を同時に走らせたい場合は、モデル作成前に以下のようにすることで、GPUのメモリ使用率を抑制することができます。

import tensorflow as tf
import keras.backend as backend

config = tf.ConfigProto()
config.gpu_options.per_process_gpu_memory_fraction = 0.5
config.gpu_options.allow_growth = True
sess = tf.Session(config=config)
backend.set_session(sess)

keras2caffeでKeyErrorが起きる

Caffe 1.0.274でkeras2caffeを使った際、KeyErrorが発生します。

Traceback (most recent call last):
  File "convert_to_caffemodel.py", line 76, in 
    keras2caffe.convert(keras_model, PROTOTXT, WEIGHTS)
  File "keras2caffe\convert.py", line 76, in convert
    if layer_type=='InputLayer' or not hasattr(caffe_net, 'data'):
  File "Anaconda3\envs\py35\lib\site-packages\caffe\net_spec.py", line 180, in __getattr__
    return self.tops[name]
KeyError: 'data'

これは、hasattrがgetattrで実装されていますが、caffeがKeyErrorをAttributeErrorに置き換えていないために発生します。

How to make a class which has __getattr__ properly pickable?

class NetSpec(object):
    """A NetSpec contains a set of Tops (assigned directly as attributes).
    Calling NetSpec.to_proto generates a NetParameter containing all of the
    layers needed to produce all of the assigned Tops, using the assigned
    names."""

    def __init__(self):
        super(NetSpec, self).__setattr__('tops', OrderedDict())

    def __setattr__(self, name, value):
        self.tops[name] = value

    def __getattr__(self, name):
        return self.tops[name]

そこで、NetSpecでKeyErrorをAttributeErrorに変換します。

class NetSpec(object):
    """A NetSpec contains a set of Tops (assigned directly as attributes).
    Calling NetSpec.to_proto generates a NetParameter containing all of the
    layers needed to produce all of the assigned Tops, using the assigned
    names."""

    def __init__(self):
        super(NetSpec, self).__setattr__('tops', OrderedDict())

    def __setattr__(self, name, value):
        self.tops[name] = value

    def __getattr__(self, name):
        try:
            return self.tops[name]
        except KeyError:
            raise AttributeError(name)

これで正常にcaffemodelに変換することができます。

MacOS Mojaveで英語キーボードとして認識される

MacにChromeRemoteDesktopでログインしたあと、JISキーボードが英語キーボードとして認識される問題が起きました。この問題は再起動しても解決しませんでした。

Mojave以前の場合は「キーボードの種類を変更ボタン」がキーボード設定にあったのですが、Mojaveではなくなっているため、以下からキーボード設定アシスタントを実行する必要があります。

/system/Library/CoreService

キーボード設定アシスタントの指示に従うと、JISキーボードとして認識されました。
Search
Profile

abars

アプリとWEBサービスを開発しています。最近はUnityとGAE/pyが主戦場。

ブラウザ向けMMOのメトセライズデストラクタ、イラストSNSのイラストブック、東証の適時開示情報を検索できるTDnetSearchを開発しています。

かつてエンターブレインのTECH Win誌でATULADOを連載しました。

サイト:ABARS
Twitter:abars
Github:abars

Twitter
TopHatenar
HotEntry
Counter

アクセス解析付きカウンター。あなたのBLOGにもどうですか?登録はこちらから。

TOP/ BLOG/ LECTURE/ ONLINE/ RUINA/ ADDON/ THREAD/ METHUSELAYZE/ IPHONE/ MET_IPHONE/ ENGLISH/ RANKING