iPX社員によるブログ

iPX社員が"社の動向"から"自身の知見や趣味"、"セミナーなどのおすすめ情報"に至るまで幅広い話題を投下していくブログ。社の雰囲気を感じ取っていただけたら幸いです。

深層学習

初めに

ご無沙汰しております、iPX界の深層学習部(非公式)部長の小川です。
今回はDeep Learning(以下DL)につきまして記そうと思います。
既にありふれている情報で、インターネットを汚す事は大変恐縮してしまいますが、取り組み内容をアピールする場として発信させていただけたらと思います。

これまで道具を使う為の自己研鑽は多く積んできました、そして物体認識や深層強化学習にトライし、一定の結果も残せたと思います。

今後はエッジデバイスから始まり、DLが量産品に導入されるケースも増えてくると思います。
近い未来に問われるであろうDLの品質保証をどう担保していくか。
今一度基礎に立ち返り理論への理解を深める事、それが私に求められる次なる自己研鑽なのであります。

記事方針

記事の内容は書籍を元に構成しております、正確な情報は是非書籍をお手にとっていただけたらと思います(参考書籍の項をご参照ください)。
ここでは新入社員向けに噛み砕けるだけ噛み砕き説明する事に徹します。
よって事実とは異なる点があることを予めご了承願います。
また、私自身も未熟至る為、数式や説明が間違っている可能性が有ります点も併せてご容赦いただけたら幸いです。

記事中のプログラムはpython3で実装しています。

DLの目的

ある関数を近似(まね)することです。
利点としては下記があると考えています。

  • 既知の計算量が膨大な関数を近似することで高速化する
  • 未知の関数を近似することで実装が困難な処理を実現する

これら恩恵を受ける為には道具と使い方を学ぶ必要が有ります。
具体的にはパーセプトロン、活性化関数、多層ネットワークといった枠組みや、順伝搬や誤差逆伝播法などの枠組みの使い方です。

ニューラルネットワーク

ここではニューラルネットワークの構築に必要となるいくつかの枠組みを一つづつ知っていきます。

パーセプトロン

いくつかの入力をまとめて一つの出力を返す枠組みです。
登場人物は下記3名です。

名称 役割
ユニットさん 入力とか出力のあの丸(○)の部分
重みさん 重みさんを良しなに変化させる事が学習
バイアスさん 微調整

数式

u_j = \sum_{i=1}^I w_{ji} x_i + b_j
行列版

u = Wx+b
魚のような記号はΣ(シグマ)で、直訳すると総和です。
プログラムではsum変数に計算結果をループで足す処理に当たります。

pythonプログラムにて行列演算ライブラリのnumpyを用いて表現してみます。

import numpy as np

I = 4
J = 1
x = np.random.rand(I)
W = np.random.rand(J,I)
b = np.random.rand(J)

# for文版
u = .0
for i in range(I):
    u += W[0,i] * x[i]
else:
    u += b[0]
print(u)

# 行列版
u_d = np.dot(W,x)+b
print(u_d) 

numpyの演算を使うととっても楽でした。

活性化関数

パーセプトロンはあくまで複数の入力に重みとバイアスを加えて1つの出力を行う枠組みでした。
出力にある変換を行う活性化関数が知られています。
DLでは非線形関数(1本の直線ではない)を適用することがお決まりです。

名称 特徴
ロジスティック関数さん 範囲が0~1  f(u)=\frac{1}{1+e^{-u}}
双曲線正接関数さん 範囲が-1~1  f(u) = \tanh(u)
正規化線形関数(ReLU)さん マイナスが無い  f(u) = \max(u,0)
恒等写像さん そのまま  f(u) = u

pythonにてグラフ描画ライブラリのmatplotlibを用いて関数の形を可視化してみます。

import numpy as np
import matplotlib.pyplot as plt

x = np.arange(-5., 5., .1)

def logistic(u):
    return 1/(1+np.exp(-u))

def hyperbolic(u):
    return np.tanh(u)

def relu(u):
    return np.maximum(u,0)

plt.plot(x, logistic(x), label='logistic', linestyle='--')
plt.plot(x, hyperbolic(x), label='hyperbolic', linestyle='--')
plt.plot(x, relu(x), label='relu', linestyle='--')

plt.legend()
plt.xlim(-5.2, 5.2)
plt.ylim(-1.2, 1.2)
plt.title('activation functions')
plt.show()

f:id:ipx-writer:20180521015559p:plain

いずれも確かに直線ではない事と、データ範囲と形に特徴がある事が分かりました。

多層ネットワーク

パーセプトロンと、活性化関数を組み合わせて、ユニットを横にも積んで多層化します。
多層化することでニューラルネットワークの表現力が高まります。
層の上から計算していき、最終的な出力を求める事を順伝搬と呼びます。

ネットワークの作成と順伝搬をpythonで表現してみます。
書籍「ゼロから作るDeep Learning - Pythonで学ぶディープラーニングの理論と実装」の例を参考にしました。

from functools import reduce
import numpy as np
import matplotlib.pyplot as plt

class layer:
    def __init__(self, W, b, f):
        self.W = W
        self.b = b
        self.f = f

def logistic(u):
    return 1/(1+np.exp(-u))

def identity(u):
    return u

layer1 = layer(np.array([[.1, .3, .5], [.2, .4, .6]]), np.array([.1, .2, .3]), logistic)
layer2 = layer(np.array([[.1, .4], [.2, .5], [.3, .6]]), np.array([.1, .2]), logistic)
layer3 = layer(np.array([[.1,.3], [.2, .4]]), np.array([.1, .2]), identity)
network = [layer1, layer2, layer3]

x = np.array([1., .5])
y = reduce(lambda z, l: l.f(np.dot(z, l.W) + l.b), network, x)
print(y)    # output:[ 0.31682708  0.69627909]

1つ目の層は入力層、最後の層は出力層と呼ばれます。
また、各層の出力をzと置き、任意の総数Lと置くと多層ネットワークは下記に一般化出来ます。

 u^{(l+1)} = W^{(l+1)} z^{(l)}+b^{(l+1)}

 z^{(l+1)} = f(u^{(l+1)})

 y≡z^{(L)}


≡(合同)は左辺を右辺で定義する意味です。

以降は書籍「深層学習」に則り、ネットワークのパラメータ全てを成分に持つベクトルwを定義し、下記で表す事とします。

 y(x;w)

学習

ここまでで多層ネットワークを定義し、順伝搬することで出力yを得ることが出来るようになりました。
次に必要な事は多層ネットワークの枠組みを用いて、重みを調整する事、即ち学習です。
任意のデータから適切な重みを調整する為にはいくつか覚えることが必要です。

  • 教師(訓練)データ
  • 誤差
  • 回帰
  • 分類
  • (時間切れ... TBD)

教師(訓練)データ

DLではデータから任意の関数を近似することが目的でした、ここでデータとは入力と出力の組み合わせとなっており、教師データと呼ばれます。

誤差

全ての教師データの入力と出力(答え)と、ニューラルネットワークの出力が一致すれば、学習が完了したということになります。
そこで教師データと、現在のニューラルネットワークがどれだけかけ離れているかを表す指標が誤差と呼ばれます。
つまり学習とは誤差を返す誤差関数の結果が最小とする事です。

回帰

DLでは解きたい問題によって出力が変わります。
回帰問題では連続値の推定が問題設定となります。
例えば、ある入力から適切なモーターのトルク値を出力するような問題は、この回帰問題です。
回帰問題の場合は誤差関数として二乗誤差がよく用いられます。
目標出力(答え)をdと置くと、下記数式で表せます。

 ||d-y(x;w)||^2

全教師データに適用する場合は、1/2を掛ける事で、微分計算の際に二乗と相殺されるようにするのが一般的です。
回帰問題の場合はこの二乗誤差関数のwを最小化することが学習タスクとなります。

 E(w) = \frac{1}{2} \sum_{n=1}^{N}||d_n - y(x_n;w)||^{2}

分類

分類問題では離散値(不連続な数値)の推定となります。
例えば、手書きした0~9の文字画像から、手書きされた数値が何であるかを推定するような問題は、この分類問題です。

二値分類

先ずは分類の中でも2つに分ける二値分類から理解していきます。
簡単の為、出力ユニットは1つで、0-1の値が0.5から上下どちらにあるかで二値の内どちらかを表現することにします。
∈は右辺が左辺に含まれるという意味です。

 d ∈ \{0,1\}

入力xが1であることを表すために、事後確率モデルを用いることが一般的です。
書籍「深層学習」に則り、下記で表すことにします。

 p(d=1|x)

DLでは事後確率をモデル化する為にニューラルネットワークを用います。
ここで2つの波線は近似を意味します。

 p(d=1|x) \approx y(x;w)

1の場合、0の場合も含めて事後確率をモデル化する場合は、べき乗を使うことで、1つの式で表すことが出来ます。
dが1の場合は右辺式中の左因子が、dが0の場合は右因子が計算されます、これはプログラムでいうところの条件演算に似ていますね。

 p(d|x) = p(d=1|x)^{d}p(d=0|x)^{1-d}

入力データxが上記の確率分布を最もよく整合する事を定める為に、最尤推定を行う事を考えます。

最尤推定

尤度(もっともらしさ)を求める考え方です。
尤度関数L(θ)を計算し、出力を最大とするθを推定します。
寄り道になりますが、よく見る例として確率分布が正規分布に従っているという仮定の元、下記の数式が出てきます。

 f(x) = \frac{1}{\sqrt{2\pi\sigma^{2}}} \exp(-\frac{1}{2}\frac{(x-\mu)^{2}}{\sigma^{2}})

複数データの確率分布を考える場合、各データに相関が無い場合は各データが独立同一分布であると言います。
独立である事で、全体の確率は確率密度の積に等しいと考える事が出来ます。
よって下記数式で表せます。
Πは総乗という意味です、Σの掛け算バージョンです。

 P(x_1, x_2, ..., x_n) = \prod_{i=1}^{n} \frac{1}{\sqrt{2\pi\sigma^{2}}} \exp(-\frac{1}{2}\frac{(x-\mu)^{2}}{\sigma^{2}})

正規分布の場合は平均μと、偏差σを求めたい確率変数として、尤度関数を定義します。

 L(\mu,\sigma) = \prod_{i=1}^{n} \frac{1}{\sqrt{2\pi\sigma^{2}}} \exp(-\frac{1}{2}\frac{(x-\mu)^{2}}{\sigma^{2}})

最尤推定ではL(μ,σ)が最大となるような確率変数μ、σを求める事がタスクとなります。

ここまで正規分布を例として、尤度関数の成り立ちを追ってきました。
今回はニューラルネットワークによって事後確率を表現することが目的となります。
よって尤度関数は下記と考えることが出来ます。

 L(w) = \prod_{n=1}^{N} p(d_n|x_n;w)

前項の二値分類より、下記の数式に置き換えて考えることが出来ます。

 L(w) = \prod_{n=1}^{N} \{y(x_n;w)\}^{d_n} \{1 - y(x_n;w)\}^{1-d_n}

ここまでで、二値分類における尤度関数を定義しました。
この尤度関数にもうひと手間加えて、誤差関数を定義していきます。
ここでいきなりlog(対数)が登場します。

単調性

logには単調性という性質があります。
単調性の中で、単調増加と呼ばれる性質は下記数式におけるxが増加した場合にyも増加するという性質です。

 y = f(x)

この性質から、定義した尤度関数にlogを適用しても、尤度関数として成り立つと考えることが出来ます。

 L(w) = \log [\prod_{n=1}^{N} \{y(x_n;w)\}^{d_n} \{1 - y(x_n;w)\}^{1-d_n} ]

次に下記のlogの公式から累乗と総乗を除外することが出来ます。

 \log_a MN = \log_a M + \log_a N

 \log_a M^{k} = k\log_a M

変形して累乗と総乗を除外した尤度関数は下記となります。

 L(w) = \sum_{n=1}^{N} [d_n \log y(x_n;w) + (1-d_n) \log \{1-y(x_n;w)\}^{1-d_n} ]

ここで尤度関数はL(w)を最大にすることが目的でした。
誤差関数では誤差を最小にすることが目的なので、符号を逆転する必要が有ります。

 E(w) = -\sum_{n=1}^{N} [d_n \log y(x_n;w) + (1-d_n) \log \{1-y(x_n;w)\}^{1-d_n} ]

これで二値分類における誤差関数が定義出来ました。

条件付き確率

早速誤差関数を使って学習の為の勉強に入って行きたいところですが、活性化関数には何を選択すれば良いでしょうか?
ロジスティック関数を用いると仮定して、事後確率モデルとマッチしているかを確認してみます。
条件付き確率の公式より、事後確率は下記事前確率で計算されると見なすことが出来ます。

 p(d=1|x) = \frac{p(x,d=1)}{p(x,d=0) + p(x,d=1)}

上記がuのロジスティック関数と同義であることを確認するために、下記の仮定を置きます。
ここで log x は底にネイピア数(e)が省略されているものとします。

 u ≡ \log \frac{p(x,d=1)}{p(x,d=0)}

logの公式より、上記式を変形します

 x = a^{y}

 y = \log_a x

 \frac{p(x,d=1)}{p(x,d=0)} = e^{u}

次に条件付き確率の公式より変形した式を、p(x,d=0)で割り、更に変形していきます。

 \frac{\frac{p(x,d=1)}{p(x,d=0)}} {\frac{p(x,d=0) + p(x,d=1)}{p(x,d=0)}}

約分します。

 \frac{\frac{p(x,d=1)}{p(x,d=0)}} {1+ \frac{p(x,d=1)}{p(x,d=0)}}

logの公式で変形した式を当てはめます。

 \frac{e^{u}} {1+ e^{u}}

さらにeuで割ります。

 \frac{\frac{e^{u}}{e^{u}}} {\frac{1+ e^{u}}{e^{u}}}

約分します。

 \frac{1} {\frac{1}{e^{u}} + 1}

逆数の公式により、式を変形します。

 \frac{1} {1 + e^{-u}}

上記はロジスティック関数さんと同じ式なので、事後確率はuのロジスティック関数だということが分かりました。

 p(d=1|x) = \frac{1} {1 + e^{-u}}

活性化関数にはロジスティック関数を用いれば良さそうです。

最後に

大変申し訳ございません、力尽きました。
実際に二値分類の学習を行うコードまで載せたかったですが、書籍「深層学習」の P17-18 への理解に時間が取られました。
学習を行うためには、微分法やチェーンルール、勾配や、勾配降下法、そして誤差逆伝播法を学ぶ必要が有ります。
次回は上記を載せた上で、学習を実施するpythonプログラムを載せた内容をゴールと定めて、執筆を頑張りたいと思います。

参考にさせていただきました書籍の著者様、わかりやすい記事を公開してくださった皆様に感謝を申し上げます。

参考書籍

参考サイト

ROSをCUDA対応してみる

こんにちは、和田です。
最近、プロジェクトでちょいちょいROSを利用することが増えてきました。

ROSってノードをちょいちょい組み合わせるだけでそれなりに動く物つくれるんで便利なんですよね。
そんな中、独自のノードを作ることも多々あるんですが、PointCloudの整形とかってCUDAを使った並列処理に向いているんだよなと。

nVidiaのJetsonTX2などを使う場合は特に、GPUを有効に使うことが大事ですし。
http://www.nvidia.co.jp/object/embedded-systems-dev-kits-modules-jp.html

そして、案外調べてみると日本語でROS+CUDAの環境構築を記事にしている人少ないんで、とりあえず書いてみようかなと言う流れです。
(英語で調べると結構出てきますが。。。)

続きを読む

うつのみやぐらし!

ご無沙汰しております。Inoです。
前回、入社してすぐに書いた記事からあっという間に半年が経過しました。時が経つのは早いものです。
今回こそは先輩たちに倣って技術的な記事を!と思いましたが、
まだまだ学習中の身で書けるまでのものも見つからないため、
入社してすぐに異動でやってきた栃木県宇都宮市の生活について書いてみたいと思います。

続きを読む

学習資料

お疲れ様です、鈴木です。
今回私の記事では私が最近学習しているwebページや書籍を紹介したいと思います。

(書籍)自動車業界MBDエンジニアのためのSimulink入門

自動車業界MBDエンジニアのためのSimulink入門-4週間で学ぶSimulink実践トレーニング- (MBD Lab Series)

自動車業界MBDエンジニアのためのSimulink入門-4週間で学ぶSimulink実践トレーニング- (MBD Lab Series)

この書籍は基本的にはSimulinkの基本的な操作方法が説明されています。
1章のモデルベース開発の概要、2章の制御設計に関わるエンジニアが学習すべきスキルの話、8章9章での要求分析・制御設計の課題はSimulink以外のツールでも活用できる内容ですのでモデル・制御開発の初心者は一読すべき内容だと思います。

(webページ) 日経xTECH 1Dシミュレーション

tech.nikkeibp.co.jp
先程紹介した書籍と重複する説明もありますが、1Dシミュレーションと2D・3Dシミュレーションとの違い、それぞれのメリットを分かりやすく説明されています。説明に用いられている画像は非因果系のシミュレーションツールを意識したもになっているのでModelicaやVHDL-AMSなどでのモデル開発のイメージを掴むのにも適していると思います。

(webページ)業務プロセス管理

https://www.questetra.com/ja/glossary/business-process-management/
業務内容を分解し、「業務の進め方」「業務のルール」についてPDCAを回す。
私自身の今の業務の進め方について見直す一助としたいです。

(webページ)より良いシステム開発のために、状態遷移設計のことを知ってほしい - Qiita

qiita.com
1Dシミュレーションでも制御モデルを開発するとき、状態遷移表や図で表現することで検討漏れの防止、設計根拠の明示化などによって品質向上の役に立つのではないかと思う。下記の書籍の購入も検討しております。

組込みエンジニアのための状態遷移設計手法―現場で使える状態遷移図・状態遷移表の記述テクニック― (MBD Lab Series)

組込みエンジニアのための状態遷移設計手法―現場で使える状態遷移図・状態遷移表の記述テクニック― (MBD Lab Series)

"Little and often fills the purse...?"

こんにちは、Hirosakiです。
早いもので、前回の投稿から半年、入社から一年経ちました。
開発作業をUbuntu上で行うことが多くなり、使い慣れていく半面、Windows環境の使いにくさを覚える機会が増えていく日々を送っています。
また、ありがたいことにDRIVE PX2上で動作させるプログラム構築をする機会が増えました。


今回はそのDRIVE PX2上で構築したプログラム中の異なる2つのプロセスが連携して動作する部分にて使用した「<共有メモリ>を使用したプロセス間通信」についてのお話です。


<余談>
本来1つのプログラムで完結させたかったところでしたが、そうできなかったのは
必要ライブラリがアーキテクチャ違いでコンパイルできないという致命的な問題があったからなのでした。
どこかで聞いたような話ですね

では続きます。

続きを読む

Linux (Ubuntu) 環境で AirSim を利用する方法

こんにちわ、 iPX のコクブンです。
Linux (Ubuntu) 環境で AirSim を利用する場合、残念ながら現時点では公式からビルド済バイナリが提供されていないため、 GitHub よりソースコードを入手して自分でビルドを行う必要があります。
今回は、 Ubuntu 環境での AirSim ビルド手順についてご紹介させていただきます。
※ AirSim の概要についてお知りになりたい方は概要紹介記事をご参照ください。
※ AirSim の最新版を Windows 環境で利用したい方は Windows 環境でのビルド方法紹介記事をご参照ください。

※ 2018/05/11 追記
本記事を投稿後、 AirSim のドキュメントが更新され、サポートされる各ツールのバージョンが変更されました。

Unreal Engine
4.17 → 4.18
CMake
記事中では特に明記していませんでしたが、 ver 3.9.0 以上が必要になります

本記事中の上記ツールのバージョンについては、適宜読み替えてください。

続きを読む

決算書について‐貸借対照表編‐

こんにちは。
気が付いたら入社1年を過ぎていた、すずきです。
数週間前から3DCGソフトでモデリング等をはじめました。そちらで何かできたらと思っていましたが、まだまだ拙いのでもう少し習得度が進んでからにしたいと思います。
今回は、自分の学習してきた会計に関わる「決算書」についてお話したいと思います。
3月が決算月の会社も多くあることでしょう。iPXでは9月が決算月の為まだ先の話ではありますが、先日社内で決算書についての話になったので、自分の復習を兼ねて記事を書いていきます。

決算書の種類

まず、決算書の種類について
貸借対照表(B/S):会社の財政状態を表記しています。資産 = 負債 + 純資産
損益計算書(P/L):1年間(会計期間)の経営成績を表記しています。収益 - 費用 = 損益 ※損益…利益と損失のこと
キャッシュフロー計算書:1年間(会計期間)の資金の動きを表記しています。
全て話そうとすると長くなるので、今回は貸借対照表をメインに記載します。

貸借対照表

貸借対照表は通称、バランスシート(Balance Sheet)と呼ばれ、B/Sと省略されます。
企業の借金の残高や保有する財産の価値を表し、左側と右側が必ず一致する特徴があります。

資産

 資産の部では、借入金や資本として調達した資金がどのような資産の購入に充てられているのか、どのような事業に投資されるのかを意味します。
 資産の部は、”流動資産”、”固定資産”、”繰延資産”に分けられます。
 ・流動資産…1年間で使い切る資産【現金、売掛金受取手形、商品・製品等のたな卸資産、仮払金、短期貸付金など】
 ・固定資産…販売目的ではなく、長期間、事業のために使用または所有する資産【建物、機械装置、車両運搬具、土地、リース資産、特許権、商標権など】
 ・繰延資産…既に代金の支払が完了、または支払義務が確定し、これに対応する役務の提供を受けたにも関わらず、その効果が将来的に継続されると期待される費用を資産として繰り延べたものです。固定資産との違いは、換金性の有無(財産的価値を有していないと繰延資産になります)【創立費、開業費、株式交付費、社債発行費など】

負債

 負債の部では、借入(借金)など外部から調達された資金を表します。外部資本・他人資本・借入資本と呼ばれることもあります。
 負債の部は、”流動負債”、”固定負債”に分けられます。
 ・流動負債…1年間で払い終わる債務【支払手形、買掛金、未払金、預り金、短期借入金、1年以内に返済予定の長期借入金など】
 ・固定負債…返済期日が1年以内に到来しない債務【社債、長期借入金、退職給付引当金など】

純資産

 純資産の部は、内部で調達する資金のことで、会社を運営するための元手と、運営して得た利益の蓄積されています。
 資本・自己資本・株主資本・内部資本とも呼ばれることがあります。
 負債の金額が資産の金額を上回り、純資産の部がマイナスとなった状況を債務超過といい、債務超過に陥ると、会社の信用は著しく低下することになります。
 負債の部は、株主資本、新株予約権などがあります。

会社の安全性の確認方法

貸借対照表は会社に現金化できるお金がいくらあるのか、支払い義務のあるお金がいくらあるのか、投資可能な金額がいくらあるのか…などの経営の資金繰りを考える上で重要な情報を読み取ることができるようになります。
その他、貸借対照表が読めるようになれば、会社の安全性を読み取ることができるようになります。

自己資本比率

 資金調達のどの程度を返済の必要のないお金で賄っているかの比率です。高ければ高いほど安全性が高いと言えます。平均率は業界によっても異なります。
 例えば、ディズニーランドを経営しているオリエンタルランドでは75%を超えています。(2017年3月の単体データ)
 オリエンタルランドではアトラクションを新設するときに億単位の投資を行いますが、銀行からの借入による資金調達では調達年限が限られているため、自己資本比率が高いことが重要になってくることがわかります。来年東京ディズニーシーに完成予定の新アトラクション ソアリン(仮)だと180億円もの金額だそうです。その他、2020年に東京ディズニーランドに新設されるエリアの投資金額は280億円もの金額です。
 ディズニー好きな私としては今から楽しみです。特にソアリンはアナハイムのディズニーに行ったときに乗りましたが、高所恐怖症の方でなければとても楽しめると思います!

流動比率

 流動資産と流動負債の割合で”流動資産 ÷ 流動負債 × 100”で求めます。これは短期間な安全性を測る指標として役立ちます。数値が高いほど安全だと考えられ、一般的に150~200%以上であると安全と言われます。

固定比率

 固定資産と固定負債の割合で”固定資産 ÷ 自己資本 × 100”で求めます。これは長期的な安全性を測る指標として役立ちます。数値が低いほど安全だと考えられ、これが100%を超えていると「借金に頼って固定資産を購入している」ということが言えます。


以上、上記のことが判断できる通り貸借対照表は会社の安全性を確認するのに重要な書類となります。
上場している会社であれば、ホームページのIR情報のところに貸借対照表B/Sと損益計算書P/Lが置いてあることが多いので、気になる会社があれば決算書を読んでみてください。

さいご

現在のモデリングの現状です。
①は数週間前に初めてBlenderを触り、作成したモデルで、③は昨日作成したモデルです。
少しずつ上達しているような気がします。
f:id:ipx-writer:20180413120448j:plain