質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Chainer

Chainerは、国産の深層学習フレームワークです。あらゆるニューラルネットワークをPythonで柔軟に書くことができ、学習させることが可能。GPUをサポートしており、複数のGPUを用いた学習も直感的に記述できます。

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

Q&A

解決済

1回答

329閲覧

CNN・セグメンテーションの重み更新量を1回ごとに表示したい

deb

総合スコア17

Chainer

Chainerは、国産の深層学習フレームワークです。あらゆるニューラルネットワークをPythonで柔軟に書くことができ、学習させることが可能。GPUをサポートしており、複数のGPUを用いた学習も直感的に記述できます。

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

0グッド

0クリップ

投稿2019/06/29 07:46

前提・実現したいこと

現在、chainerを使ってセグメンテーションを行っています。
chainerのTrainerという機能に、バッチサイズや学習モデル、エポック数などを渡すと自動で学習して答えを出してくれます。
今回は、学習の一回一回で計算して更新される重み量を可視化して表示したいと思っています。
セグメンテーションにおける重みとはカーネル(フィルタ)の値だと思うので、それを白黒の画像(扱っているのがグレースケール画像なので)として表示したいと思っています。

Trainerの中身

python

1def create_trainer(batchsize, train, val, stop, device=-1, log_trigger=(1, 'epoch')): 2 model = FullyConvolutionalNetwork(out_h=200, out_w=200) 3 train_model = PixelwiseSigmoidClassifier(model)#ここで目的関数を決めているようだ 4 5 # 最適化手法にSGDを使用(勾配降下法のひとつ) 6 optimizer = optimizers.SGD() 7 optimizer.setup(train_model) 8 9 # データセットから,指定したバッチサイズ数のデータ点をまとめて取り出して返すイテレータを定義 10 train_iter = iterators.MultiprocessIterator(train, batchsize) 11 val_iter = iterators.MultiprocessIterator(val, batchsize, repeat=False, shuffle=False) 12 13 # イテレータからデータを引き出し,モデルに渡して,目的関数の値を計算し,backwardしてパラメータを更新, 14 # までの一連の処理を行う updater を定義 15 updater = training.StandardUpdater(train_iter, optimizer, device=device) 16 17 # 様々な付加機能をExtensionとして与えられるTrainerを使用 18 trainer = training.trainer.Trainer(updater, stop, out='result_fcn') 19 20 logging_attributes = [ 21 'epoch', 'main/loss', 'main/miou', 'main/pa', 22 'val/main/loss', 'val/main/miou', 'val/main/pa'] 23 trainer.extend(extensions.LogReport(logging_attributes), trigger=log_trigger) 24 trainer.extend(extensions.PrintReport(logging_attributes), trigger=log_trigger) 25 trainer.extend(extensions.PlotReport(['main/loss', 'val/main/loss'], 'epoch', file_name='loss.png')) 26 trainer.extend(extensions.PlotReport(['main/miou', 'val/main/miou'], 'epoch', file_name='miou.png')) 27 trainer.extend(extensions.PlotReport(['main/pa', 'val/main/pa'], 'epoch', file_name='pa.png')) 28 trainer.extend(extensions.Evaluator(val_iter, train_model, device=device), name='val') 29 trainer.extend(extensions.dump_graph('main/loss')) 30 return trainer

試したこと

更新はoptimizerやStandardUpdaterの中で行われているため、重みがreturnとしてmain関数に返ってくることはありません。
上記のコード中のoptimizerの中身(今回はSGD)とStandardUpdaterの中身を読んでいるのですが、どのパラメータが重みなのか分かりません。計算のコード上での動きも知りたいです。ご教授お願いいたします。

一応、SGD・optimizerのクラスのコードを張っておきます。

SGD

1from chainer.backends import cuda 2from chainer.backends import intel64 3from chainer import optimizer 4 5 6_default_hyperparam = optimizer.Hyperparameter() 7_default_hyperparam.lr = 0.01 #学習係数の設定値 8 9 10class SGDRule(optimizer.UpdateRule): 11 12 _kernel = None 13 14 def __init__(self, parent_hyperparam=None, lr=None): 15 super(SGDRule, self).__init__(#サブクラス自身SGDRuleのスーパークラスを探す(答えはoptimizer.UpdateRule).つまりスーパークラスの初期化メソッドを継承するという宣言 16 parent_hyperparam or _default_hyperparam) 17 if lr is not None: 18 self.hyperparam.lr = lr 19 20 def update_core_cpu(self, param): 21 grad = param.grad #誤差関数の偏微分はこれ。param.gradはスーパークラスoptimizer.UpdateRule内で定義されている。 22 if grad is None: 23 return 24 if isinstance(param.data, intel64.mdarray): 25 param.data.inplace_axpby(1.0, -self.hyperparam.lr, grad) 26 else: 27 param.data -= self.hyperparam.lr * grad 28 29 def update_core_gpu(self, param): 30 grad = param.grad 31 if grad is None: 32 return 33 if SGDRule._kernel is None: 34 SGDRule._kernel = cuda.elementwise( 35 'T grad, T lr', 'T param', 36 'param -= lr * grad', 'sgd') 37 SGDRule._kernel(grad, self.hyperparam.lr, param.data) 38 39 40class SGD(optimizer.GradientMethod): 41 42 def __init__(self, lr=_default_hyperparam.lr): 43 super(SGD, self).__init__() 44 self.hyperparam.lr = lr 45 46 lr = optimizer.HyperparameterProxy('lr') 47 48 def create_update_rule(self): 49 return SGDRule(self.hyperparam) 50

(↓一部です)

optimizer

1 2class UpdateRule(object):#sgd.pyのサブクラスSGDRuleでスーパークラスとして参照されてる。 3 4 def __init__(self, parent_hyperparam=None): 5 self._pre_update_hooks = collections.OrderedDict() 6 self._post_update_hooks = collections.OrderedDict() 7 self._state = None 8 self.enabled = True 9 self.hyperparam = Hyperparameter(parent_hyperparam) 10 self.t = 0 11 self._use_fp32_update = False #TrueかFalseのboolタイプ 12 self._fp32_param = None 13 14 @property 15 def state(self): 16 """State dictionary.""" 17 return self._state 18 19 def add_hook(self, hook, name=None, timing='auto'): 20 21 if not callable(hook): 22 raise TypeError('hook function must be callable') 23 if timing not in ('pre', 'post', 'auto'): 24 raise ValueError("timing must be one of ('pre', 'post', 'auto')") 25 if timing == 'auto': 26 timing = getattr(hook, 'timing', 'pre') 27 28 if name is None: 29 name = getattr(hook, 'name', getattr(hook, '__name__', None)) 30 if name is None: 31 raise ValueError( 32 'the name of the hook function is not specified') 33 if name in self._pre_update_hooks or name in self._post_update_hooks: 34 raise ValueError('hook "{}" already exists'.format(name)) 35 36 if timing == 'pre': 37 self._pre_update_hooks[name] = hook 38 else: 39 self._post_update_hooks[name] = hook 40 41 def remove_hook(self, name): 42 43 try: 44 del self._pre_update_hooks[name] 45 except KeyError: 46 del self._post_update_hooks[name] 47 48 def update(self, param): 49 50 if not self.enabled: 51 return 52 53 self.t += 1 54 55 if self._use_fp32_update and param.dtype == numpy.float16: 56 if self._fp32_param is None: 57 self._fp32_param = variable.Variable( 58 param.array.astype(numpy.float32), 59 name=param.name) 60 fp32_param = self._fp32_param 61 fp32_param.grad = param.grad.astype(numpy.float32) 62 63 if fp32_param.data is not None: 64 self._prepare(fp32_param) 65 if param._loss_scale is not None: 66 fp32_param.grad /= param._loss_scale 67 for hook in six.itervalues(self._pre_update_hooks): 68 hook(self, fp32_param) 69 self.update_core(fp32_param) 70 for hook in six.itervalues(self._post_update_hooks): 71 hook(self, fp32_param) 72 73 param.data = fp32_param.data.astype(param.dtype) 74 fp32_param.grad = None 75 else: 76 if param.data is not None: 77 self._prepare(param) 78 if param._loss_scale is not None: 79 param.grad /= param._loss_scale 80 for hook in six.itervalues(self._pre_update_hooks): 81 hook(self, param) 82 self.update_core(param) 83 for hook in six.itervalues(self._post_update_hooks): 84 hook(self, param) 85 86 def update_core(self, param): 87 88 with cuda.get_device_from_array(param.data) as dev: 89 if int(dev) == -1: 90 self.update_core_cpu(param) 91 else: 92 self.update_core_gpu(param) 93 94 def update_core_cpu(self, param): 95 96 raise NotImplementedError 97 98 def update_core_gpu(self, param): 99 100 raise NotImplementedError 101 102 def init_state(self, param): 103 104 pass 105 106 def serialize(self, serializer): 107 108 self.t = serializer('t', self.t) 109 if self.state is None: 110 if isinstance(serializer, serializer_module.Deserializer): 111 # try to initialize the state to retrieve state entries 112 self._state = {} 113 self_copy = copy.copy(self) 114 arr = numpy.empty(1, dtype=numpy.float32) 115 self_copy.init_state(variable.Variable(arr, grad=arr)) 116 117 for key in self._state: 118 try: 119 value = serializer(key, None) 120 except KeyError: 121 if self.enabled: 122 raise 123 value = None 124 # leave the update rule state as `None` if the keys are not 125 # contained in the snapshot, so that these states can be 126 # automatically initialized with the `_prepare` method 127 if value is None: 128 self._state = None 129 break 130 else: 131 self._state[key] = value 132 else: 133 for key in self._state: 134 self._state[key] = serializer(key, self._state[key]) 135 136 def _prepare(self, param): 137 with cuda.get_device_from_array(param.data) as device: 138 state = self.state 139 if state is None: 140 state = self._state = {} 141 self.init_state(param) 142 143 for name, value in six.iteritems(state): 144 if not isinstance(value, (numpy.ndarray, cuda.ndarray)): 145 continue 146 value_device = cuda.get_device_from_array(value) 147 if value_device.id != device.id: 148 if device.id >= 0: 149 state[name] = cuda.to_gpu(value) 150 else: 151 state[name] = cuda.to_cpu(value) 152 153 def use_fp32_update(self, flag=True): 154 155 self._use_fp32_update = flag 156

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Q71

2019/06/29 13:27

iPhone からで調べられないからこっちで。 Chain から導出して、ネットワークを構成しているクラスに定義している Convolution_2d の W のはず。 Python のデバッグ環境があるなら、__call__ などで止めて、内容を確認してみましょう。
deb

2019/06/30 06:55

Convolution_2d内のforward関数の中にプリント文を入れたら重みWを表示できました! optimizerやStandrdUpdaterは型であって具体的な値はConvolution_2dに出てくるのですね。 ご回答ありがとうございました。
guest

回答1

0

自己解決

chainer/links/connection/convolution_2d.py の クラスConvolution2D の forward関数内にある、self.Wが重みパラメータ。このままではVariable型なのでself.W.dataとして配列にすれば、plt.omshow(im)で表示可能。

投稿2019/06/30 09:30

deb

総合スコア17

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問