覚え書きブログ

mmdVAEを用いたMNISTの復元

以下のMaximum Mean Discrepancyを参考に、MNISTの画像を復元するAutoEncoderを作ってみた。
szhao.me

コード一式は、以下のレポジトリに置いてある。
github.com

フォルダ構成

  • MNIST:

http://yann.lecun.com/exdb/mnist/
からダウンロードしたMNISTのデータ(gz形式)を置く。

  • visualization:pklファイルと、元画像と復元画像のペアの画像を保存
  • models:tensorflowのチェックポイントを保存
  • input_data.py:MNISTのデータ読み込むコード

https://github.com/tensorflow/tensorflow/blob/r0.7/tensorflow/examples/tutorials/mnist/input_data.py

  • mmd_VAE.py:AutoEncoderのコード(これを実行する)

コードの内容:


実行結果の例:

Image, iteration: 0, Negative log likelihood is 0.132817
Image, iteration: 1, Negative log likelihood is 0.112096
Image, iteration: 2, Negative log likelihood is 0.103636
Image, iteration: 3, Negative log likelihood is 0.094504
Image, iteration: 4, Negative log likelihood is 0.094447
Image, iteration: 5, Negative log likelihood is 0.107632
Image, iteration: 6, Negative log likelihood is 0.096937
Image, iteration: 7, Negative log likelihood is 0.086263
Image, iteration: 8, Negative log likelihood is 0.075665
Image, iteration: 9, Negative log likelihood is 0.083440
Image, iteration: 10, Negative log likelihood is 0.076919
Image, iteration: 11, Negative log likelihood is 0.068307
Image, iteration: 12, Negative log likelihood is 0.070534
Image, iteration: 13, Negative log likelihood is 0.075518
Image, iteration: 14, Negative log likelihood is 0.084493
Image, iteration: 15, Negative log likelihood is 0.075175
Image, iteration: 16, Negative log likelihood is 0.075251
Image, iteration: 17, Negative log likelihood is 0.081132
Image, iteration: 18, Negative log likelihood is 0.076310
Image, iteration: 19, Negative log likelihood is 0.070021
Image, iteration: 20, Negative log likelihood is 0.067716
...
Image, iteration: 990, Negative log likelihood is 0.004927
Image, iteration: 991, Negative log likelihood is 0.004771
Image, iteration: 992, Negative log likelihood is 0.005030
Image, iteration: 993, Negative log likelihood is 0.004839
Image, iteration: 994, Negative log likelihood is 0.004924
Image, iteration: 995, Negative log likelihood is 0.004720
Image, iteration: 996, Negative log likelihood is 0.004871
Image, iteration: 997, Negative log likelihood is 0.004735
Image, iteration: 998, Negative log likelihood is 0.004988
Image, iteration: 999, Negative log likelihood is 0.004945
Image, iteration: 1000, Negative log likelihood is 0.005165

0反復目:
f:id:hirotaka_hachiya:20180623104203p:plain

50反復目:
f:id:hirotaka_hachiya:20180623104223p:plain

100反復目:
f:id:hirotaka_hachiya:20180623104249p:plain

150反復目:
f:id:hirotaka_hachiya:20180623104332p:plain

200反復目:
f:id:hirotaka_hachiya:20180623104540p:plain

1000反復目:
f:id:hirotaka_hachiya:20180623121732p:plain

tensorflow版のyolo2のインストールと学習

yolo2のtensorflow版がいくつかgithubに上がっているので、 thtrieuのdarkflowをインストールして、学習させてみた試してみた。

thtrieuのdarkflow
github.com

インストール

インストールの手順は以下の通り。

> git clone https://github.com/thtrieu/darkflow
> python3 setup.py build_ext --inplace
> pip install -e .
> pip install .

内容としては、setup.pyを用いてdarkflow/cython_utilsに、nms(non maximum supression)とbb関連のcythonコードがあるので、コンパイルし、darkflowパッケージをインストールしている。

次に、yolo2の学習済みのモデルファイルyolov2.weightsをダウンロードし、binフォルダに置く。

> cd bin
> wget https://pjreddie.com/media/files/yolov2.weights

flowを用いた検出

そして、flowを以下のように実行する。

> flow --model cfg/yolo.cfg --load bin/yolov2.weights
/home/hachiya/works/yolo2/darkflow/darkflow/dark/darknet.py:54: UserWarning: ./cfg/yolov2.cfg not found, use cfg/yolo.cfg instead
  cfg_path, FLAGS.model))
Parsing cfg/yolo.cfg
Loading bin/yolov2.weights ...
Successfully identified 203934260 bytes
Finished in 0.04647064208984375s
Model has a coco model name, loading coco labels.

Building net ...
Source | Train? | Layer description                | Output size
-------+--------+----------------------------------+---------------
       |        | input                            | (?, 608, 608, 3)
 Load  |  Yep!  | conv 3x3p1_1  +bnorm  leaky      | (?, 608, 608, 32)
 Load  |  Yep!  | maxp 2x2p0_2                     | (?, 304, 304, 32)
 Load  |  Yep!  | conv 3x3p1_1  +bnorm  leaky      | (?, 304, 304, 64)
 Load  |  Yep!  | maxp 2x2p0_2                     | (?, 152, 152, 64)
 Load  |  Yep!  | conv 3x3p1_1  +bnorm  leaky      | (?, 152, 152, 128)
 Load  |  Yep!  | conv 1x1p0_1  +bnorm  leaky      | (?, 152, 152, 64)
 Load  |  Yep!  | conv 3x3p1_1  +bnorm  leaky      | (?, 152, 152, 128)
 Load  |  Yep!  | maxp 2x2p0_2                     | (?, 76, 76, 128)
 Load  |  Yep!  | conv 3x3p1_1  +bnorm  leaky      | (?, 76, 76, 256)
 Load  |  Yep!  | conv 1x1p0_1  +bnorm  leaky      | (?, 76, 76, 128)
 Load  |  Yep!  | conv 3x3p1_1  +bnorm  leaky      | (?, 76, 76, 256)
 Load  |  Yep!  | maxp 2x2p0_2                     | (?, 38, 38, 256)
 Load  |  Yep!  | conv 3x3p1_1  +bnorm  leaky      | (?, 38, 38, 512)
 Load  |  Yep!  | conv 1x1p0_1  +bnorm  leaky      | (?, 38, 38, 256)
 Load  |  Yep!  | conv 3x3p1_1  +bnorm  leaky      | (?, 38, 38, 512)
 Load  |  Yep!  | conv 1x1p0_1  +bnorm  leaky      | (?, 38, 38, 256)
 Load  |  Yep!  | conv 3x3p1_1  +bnorm  leaky      | (?, 38, 38, 512)
 Load  |  Yep!  | maxp 2x2p0_2                     | (?, 19, 19, 512)
 Load  |  Yep!  | conv 3x3p1_1  +bnorm  leaky      | (?, 19, 19, 1024)
 Load  |  Yep!  | conv 1x1p0_1  +bnorm  leaky      | (?, 19, 19, 512)
 Load  |  Yep!  | conv 3x3p1_1  +bnorm  leaky      | (?, 19, 19, 1024)
 Load  |  Yep!  | conv 1x1p0_1  +bnorm  leaky      | (?, 19, 19, 512)
 Load  |  Yep!  | conv 3x3p1_1  +bnorm  leaky      | (?, 19, 19, 1024)
 Load  |  Yep!  | conv 3x3p1_1  +bnorm  leaky      | (?, 19, 19, 1024)
 Load  |  Yep!  | conv 3x3p1_1  +bnorm  leaky      | (?, 19, 19, 1024)
 Load  |  Yep!  | concat [16]                      | (?, 38, 38, 512)
 Load  |  Yep!  | conv 1x1p0_1  +bnorm  leaky      | (?, 38, 38, 64)
 Load  |  Yep!  | local flatten 2x2                | (?, 19, 19, 256)
 Load  |  Yep!  | concat [27, 24]                  | (?, 19, 19, 1280)
 Load  |  Yep!  | conv 3x3p1_1  +bnorm  leaky      | (?, 19, 19, 1024)
 Load  |  Yep!  | conv 1x1p0_1    linear           | (?, 19, 19, 425)
-------+--------+----------------------------------+---------------
Running entirely on CPU
2018-06-13 13:24:26.305912: I tensorflow/core/platform/cpu_feature_guard.cc:137] Your CPU supports instructions that this TensorFlow binary was not compiled to use: SSE4.1 SSE4.2 AVX AVX2 FMA
2018-06-13 13:24:27.013552: I tensorflow/stream_executor/cuda/cuda_gpu_executor.cc:892] successful NUMA node read from SysFS had negative value (-1), but there must be at least one NUMA node, so returning NUMA node zero
2018-06-13 13:24:27.013818: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1030] Found device 0 with properties:
name: GeForce GTX 1080 Ti major: 6 minor: 1 memoryClockRate(GHz): 1.582
pciBusID: 0000:01:00.0
totalMemory: 10.91GiB freeMemory: 10.75GiB
2018-06-13 13:24:27.013833: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1120] Creating TensorFlow device (/device:GPU:0) -> (device: 0, name: GeForce GTX 1080 Ti, pci bus id: 0000:01:00.0, compute capability: 6.1)
Finished in 4.2318079471588135s

Forwarding 8 inputs ...
Total time = 3.7926931381225586s / 8 inps = 2.1093190797819523 ips
Post processing 8 inputs ...
Total time = 0.30597639083862305s / 8 inps = 26.145808106545484 ips

「/cfg/yolov2.cfg not found」というwarningが出ているが、代わりに「cfg/yolo.cfg」が読み込まれているようだ。8枚の画像に対し、0.3秒で処理したと表示されている。GTX1080Tiなのでそこそこ速い?
8枚の画像は「sample_img」以下にあり、検出結果は、sample_img/outに保存されている。以下が結果の例である。
f:id:hirotaka_hachiya:20180613133208p:plain

ちなみに、引数に「--json」を付けると、sample_img/outにjsonの拡張子のファイルが出力され、以下のように検出したBBのラベル、スコア、座標を出力してくれる。なんとも便利。

[{"label": "person", "confidence": 0.82, "topleft": {"x": 189, "y": 95}, "bottomright": {"x": 271, "y": 380}}, {"label": "dog", "confidence": 0.8, "topleft": {"x": 69, "y": 258}, "bottomright": {"x": 209, "y": 355}}, {"label": "horse", "confidence": 0.89, "topleft": {"x": 397, "y": 127}, "bottomright": {"x": 605, "y": 352}}]

flowを用いた学習

学習は、引数に--trainを付ければよい。

> flow --model cfg/yolo.cfg --load bin/yolov2.weights --train --gpu 1.0

ただし、そのまま実行すると以下のエラーがでる。
「Error: Annotation directory not found ../pascal/VOCdevkit/ANN/ .」
ちなみに、--gpuGPUをどれくらい使うかを0~1の範囲で指定している。GPUのIDではないので注意。

darkflow/default.pyを見ると以下のように、datasetとannotationが設定されているので、引数としてdatasetとannotationを自分のデータに合わせて設定すればよいとのこと。しかも、アノテーションはpascalVOC形式のようだ。

self.define('dataset', '../pascal/VOCdevkit/IMG/', 'path to dataset directory')
self.define('annotation', '../pascal/VOCdevkit/ANN/', 'path to annotation directory')

早速kittiデータで学習したいところだが、今回は、pascal VOC2007で試してみた。

> mkdir data
> cd data
> curl -O https://pjreddie.com/media/files/VOCtest_06-Nov-2007.tartar xf VOCtest_06-Nov-2007.tar
> tar xf VOCtest_06-Nov-2007.tar
> ls VOCdevkit/VOC2007/
Annotations  ImageSets  JPEGImages  SegmentationClass  SegmentationObject

datasetは「data/VOCdevkit/VOC2007/JPEGImages」、annotationは[
data/VOCdevkit/VOC2007/Annotations」にそれぞれあるので、引数で以下のように指定してflowを実行する。ただし、GPUのメモリの関係上モデルはtiny-yolo.cfgを用いて、学習方法としてadamを用いた。

>  flow --model cfg/tiny-yolo.cfg --train --gpu 1.0 --dataset "data/VOCdevkit/VOC2007/JPEGImages/" --annotation "data/VOCdevkit/VOC2007/Annotations" --trainer adam
Parsing cfg/tiny-yolo.cfg
Loading None ...
Finished in 5.0067901611328125e-05s
Model has a coco model name, loading coco labels.

Building net ...
Source | Train? | Layer description                | Output size
-------+--------+----------------------------------+---------------
       |        | input                            | (?, 416, 416, 3)
 Init  |  Yep!  | conv 3x3p1_1  +bnorm  leaky      | (?, 416, 416, 16)
 Load  |  Yep!  | maxp 2x2p0_2                     | (?, 208, 208, 16)
 Init  |  Yep!  | conv 3x3p1_1  +bnorm  leaky      | (?, 208, 208, 32)
 Load  |  Yep!  | maxp 2x2p0_2                     | (?, 104, 104, 32)
 Init  |  Yep!  | conv 3x3p1_1  +bnorm  leaky      | (?, 104, 104, 64)
 Load  |  Yep!  | maxp 2x2p0_2                     | (?, 52, 52, 64)
 Init  |  Yep!  | conv 3x3p1_1  +bnorm  leaky      | (?, 52, 52, 128)
 Load  |  Yep!  | maxp 2x2p0_2                     | (?, 26, 26, 128)
 Init  |  Yep!  | conv 3x3p1_1  +bnorm  leaky      | (?, 26, 26, 256)
 Load  |  Yep!  | maxp 2x2p0_2                     | (?, 13, 13, 256)
 Init  |  Yep!  | conv 3x3p1_1  +bnorm  leaky      | (?, 13, 13, 512)
 Load  |  Yep!  | maxp 2x2p0_1                     | (?, 13, 13, 512)
 Init  |  Yep!  | conv 3x3p1_1  +bnorm  leaky      | (?, 13, 13, 1024)
 Init  |  Yep!  | conv 3x3p1_1  +bnorm  leaky      | (?, 13, 13, 1024)
 Init  |  Yep!  | conv 1x1p0_1    linear           | (?, 13, 13, 425)
-------+--------+----------------------------------+---------------
GPU mode with 1.0 usage
cfg/tiny-yolo.cfg loss hyper-parameters:
        H       = 13
        W       = 13
        box     = 5
        classes = 80
        scales  = [1.0, 5.0, 1.0, 1.0]
]
...
Dataset size: 4952
Dataset of 4952 instance(s)
Training statistics:
        Learning rate : 1e-05
        Batch size    : 16
        Epoch number  : 1000
        Backup every  : 2000
step 1 - loss 108.20623016357422 - moving ave loss 108.20623016357422
step 2 - loss 108.07720184326172 - moving ave loss 108.19332733154297
step 3 - loss 108.5759048461914 - moving ave loss 108.23158508300781
step 4 - loss 110.49064636230469 - moving ave loss 108.4574912109375
step 5 - loss 111.99656677246094 - moving ave loss 108.81139876708986
step 6 - loss 109.51751708984375 - moving ave loss 108.88201059936524
step 7 - loss 107.66697692871094 - moving ave loss 108.76050723229982
step 8 - loss 109.469482421875 - moving ave loss 108.83140475125734
...
Checkpoint at step 1125
step 1126 - loss 84.48749542236328 - moving ave loss 85.27347111125957
step 1127 - loss 84.01033020019531 - moving ave loss 85.14715702015314
step 1128 - loss 84.40534210205078 - moving ave loss 85.07297552834291
step 1129 - loss 85.56282043457031 - moving ave loss 85.12196001896565
step 1130 - loss 87.02748107910156 - moving ave loss 85.31251212497924

学習を回すとckptというフォルダが作られて、そこにチェックポイントが保存されるようになっている。ちなみに、10000回くらい回すとlossが5あたりまで減る。ただし、tiny-yolo.cfgはクラス数が80になっていて、MS COCO用のファイル設定ファイルであることに後から気づいた。そこで、cfg/yolo-voc.cfgで以下のように学習してみた。

flow --model cfg/yolo-voc.cfg --train --gpu 1.0 --dataset "data/VOCdevkit/VOC2007/JPEGImages/" --annotation "data/VOCdevkit/VOC2007/Annotations" --trainer adam
...
GPU mode with 1.0 usage
cfg/yolo-voc.cfg loss hyper-parameters:
        H       = 13
        W       = 13
        box     = 5
        classes = 20
        scales  = [1.0, 5.0, 1.0, 1.0]
Building cfg/yolo-voc.cfg loss
Building cfg/yolo-voc.cfg train op
2018-06-14 00:11:42.967112: I tensorflow/core/platform/cpu_feature_guard.cc:137] Your CPU supports instructions that this TensorFlow binary was not compiled to use: SSE4.1 SSE4.2 AVX AVX2 FMA
2018-06-14 00:11:43.538943: I tensorflow/stream_executor/cuda/cuda_gpu_executor.cc:892] successful NUMA node read from SysFS had negative value (-1), but there must be at least one NUMA node, so returning NUMA node zero
2018-06-14 00:11:43.539323: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1030] Found device 0 with properties:
name: GeForce GTX 1080 Ti major: 6 minor: 1 memoryClockRate(GHz): 1.582
pciBusID: 0000:01:00.0
totalMemory: 10.91GiB freeMemory: 10.75GiB
2018-06-14 00:11:43.539337: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1120] Creating TensorFlow device (/device:GPU:0) -> (device: 0, name: GeForce GTX 1080 Ti, pci bus id: 0000:01:00.0, compute capability: 6.1)
2018-06-14 00:11:43.541108: E tensorflow/stream_executor/cuda/cuda_driver.cc:936] failed to allocate 10.91G (11712987136 bytes) from device: CUDA_ERROR_OUT_OF_MEMORY
...
step 113 - loss 107.9711685180664 - moving ave loss 107.79369719607465
step 114 - loss 108.29700469970703 - moving ave loss 107.84402794643789
step 115 - loss 107.34602355957031 - moving ave loss 107.79422750775115
step 116 - loss 109.22856140136719 - moving ave loss 107.93766089711275
step 117 - loss 106.66355895996094 - moving ave loss 107.81025070339757
step 118 - loss 109.05477905273438 - moving ave loss 107.93470353833126
step 119 - loss 107.35346984863281 - moving ave loss 107.87658016936142
step 120 - loss 107.55178833007812 - moving ave loss 107.8441009854331
step 121 - loss 108.16707611083984 - moving ave loss 107.87639849797378
step 122 - loss 107.94886779785156 - moving ave loss 107.88364542796157
step 123 - loss 108.37859344482422 - moving ave loss 107.93314022964783
step 124 - loss 106.92852783203125 - moving ave loss 107.83267898988618
step 125 - loss 108.65249633789062 - moving ave loss 107.91466072468663
Checkpoint at step 125
...
Finish 5 epoch(es)
step 1546 - loss 68.74520874023438 - moving ave loss 69.44457628681288
step 1547 - loss 68.43368530273438 - moving ave loss 69.34348718840502
step 1548 - loss 68.29949188232422 - moving ave loss 69.23908765779694
step 1549 - loss 69.23208618164062 - moving ave loss 69.23838751018131
step 1550 - loss 69.6432876586914 - moving ave loss 69.27887752503233
step 1551 - loss 69.58462524414062 - moving ave loss 69.30945229694316
step 1552 - loss 67.54881286621094 - moving ave loss 69.13338835386995
step 1553 - loss 68.92791748046875 - moving ave loss 69.11284126652983
step 1554 - loss 68.00341033935547 - moving ave loss 69.00189817381239
...
step 57833 - loss 3.7261016368865967 - moving ave loss 4.266748164827713
step 57834 - loss 2.4047257900238037 - moving ave loss 4.080545927347322
step 57835 - loss 4.587594509124756 - moving ave loss 4.131250785525066
step 57836 - loss 2.978076934814453 - moving ave loss 4.015933400454005
step 57837 - loss 5.362588882446289 - moving ave loss 4.150598948653233

上記のように、CUDA_ERROR_OUT_OF_MEMORYがでたものの、学習がまわり収束した。

ネットワーク構成

最後の1x1 conv

Init | Yep! | conv 1x1p0_1 linear | (?, 13, 13, 425)

の出力の425フィルターの内訳は、以下のようになっている。
※詳細は、「darkflow/cython_utils/cy_yolo2_findboxes.pyx」を参照するとよい。

ディメンションクラスターanchors(5つ) × { bboxの座標(4次元) + confidence(1次元) + 80クラス}

なお、bboxの座標の順番は、以下のようになっている。

  1. x座標の特徴マップ上の残差スコア(最終的にはsigmoidをかけるので、最大で1ピクセルしか移動しない)
  2. y座標の特徴マップ上の残差スコア(最終的にはsigmoidをかけるので、最大で1ピクセルしか移動しない)
  3. anchorの幅に対する対数ratio(倍率)
  4. anchorの高さに対する対数ratio(倍率)

また、cfg/yolo.cfgファイルにて設定されている以下のanchorsは、幅、高さの順番で5個のアンカーを設定している。また、MS COCOデータセットhttp://cocodataset.org/#home)を想定しているためクラス数が80個ある。

[region]
anchors =  0.57273, 0.677385, 1.87446, 2.06253, 3.33843, 5.47434, 7.88282, 3.52778, 9.77052, 9.16828
bias_match=1
classes=80
coords=4
num=5

OpenAI GymのインストールとQ学習の実装(Windows)

windows subsystem for Linuxubuntu環境に、OpenAI Gymをインストールし、Q学習してみた。以下は、手順のメモである。

準備

1) windows subsystem for Linuxの設定とUbuntuのインストール
Qiitaのページhttps://qiita.com/Aruneko/items/c79810b0b015bebf30bbを参考にして、windows subsystem for Linuxの設定を行い、Ubuntuをインストールした。

2)Anacondaのインストール
hirotaka-hachiya.hatenablog.com
を参考にし、wgetでAnacondaのLinux版「Anaconda3-5.0.1-Linux-x86_64.sh」をwgetでダウンロードし、実行してインストール。

~/.bashrcにAnaconda3のパスを設定し、「source ~/.bashrc」を実行。

export PATH=/mnt/c/Users/hachiya/Documents/works/anaconda3/bin:$PATH


3) WindowsのXサーバXmingのインストール
windowsUbuntuがインストールできると言っても、GUI無しの状態でインストールされるので、自前でXserverを用意する必要がある。幸い、Windowsにはフリーでも優れたXserver「Xming」があるので、それをインストールする。具体的には、Xming-6-9-0-31-setup.exeを、
https://ja.osdn.net/projects/sfnet_xming/releases/
からダウンロードし実行してインストールした。

~/.bashrcにDISPLAYの設定をし、「source ~/.bashrc」を実行。

export DISPLAY=localhost:0.0

OpenAI Gymのインストール

Qiitaのページhttps://qiita.com/ishizakiiii/items/75bc2176a1e0b65bdd16を参考にインストールする。

1) 基本パッケージのインストール

> pip install gym

2) 基本パッケージのインストール

> sudo apt-get install -y cmake zlib1g-dev libjpeg-dev xvfb libav-tools xorg-dev libboost-all-dev libsdl2-dev swig

これらのパッケージは基本的な開発環境に関するものなので、ある程度開発用途で使っている環境であれば必要ないかもしれない。今回のwindow上のubuntuは使い始めたばかりだったので、インストールが必要だった。なお、pythonまわりのパッケージはAnaconda3を用いているため一切インストールしていない。インストールするとpython環境が2つ存在してややこしいことになるので、注意。

3) Atari社のGameおよびその他の環境ライブラリのインストール

> pip install 'gym[atari]'
> pip install 'gym[all]'


4) 動作確認
以下のように、pythonインタラクティブモードで、mountaincarの環境を読み込み、render()を実行しxmingでmountaincarが表示されるかどうか確認。

> python
>>> import gym
>>> env = gym.make('MountainCar-v0')
>>> env.reset()
array([-0.44697984,  0.        ])
>>> env.render()

f:id:hirotaka_hachiya:20180528184959p:plain

pythonを用いたQ学習の実装

Qiitaのページhttps://qiita.com/ishizakiiii/items/75bc2176a1e0b65bdd16を参考にし、mountainCarタスクを学習するQ学習のアルゴリズムオブジェクト指向で実装してみた。
github.com

コードは以下の通り(GitHubGistでも公開中)。
128行目のisDemoが「Flase」の時は158行目以降の学習が始まり、100エピソードごとにmodelsディレクトのpklファイルにQテーブルが保存される。一方、学習後にisDemoを「True」にして実行すると、136行目からのデモが始まり、保存したpklを所定のエピソード間隔(100エピソードごと)で読み込んで、各エピソードでの方策を再現してくれるようになっている。