Javascriptタイプ推論(4)-隠蔽層の更新

25858 ワード

Javascriptタイプ推論(4)-隠蔽層の更新
全体の流れに慣れたら、より多くの細部に注目できます.
前にトレーニングの過程を話した時、enhanceを話しませんでした.ダタの詳細.この部分の主な機能は隠しレイヤーを更新することです.そのコールポイントは以下の通りです.
def train():
	train_reader = create_reader(files['train']['file'], is_training=True)
	step = 0
	pp = C.logging.ProgressPrinter(freq=10, tag='Training')
	for epoch in range(num_epochs):
		trainer = create_trainer()
		epoch_end = (epoch+1) * epoch_size
		print('epoch_end=%d' % epoch_end)
		while step < epoch_end:
			data = train_reader.next_minibatch(minibatch_size, input_map={
				x: train_reader.streams.source,
				y: train_reader.streams.slot_labels
			})

			# Enhance data
			enhance_data(data, enc)
			# Train model
			trainer.train_minibatch(data)
			pp.update_with_trainer(trainer, with_metric=True)
			step += data[y].num_samples
エンハンスを説明していますdataの前に、trin.txtで生成されたctfの仕組みを説明して、トレーニングに使われるデータの本当の意味を知ることができます.
ctfファイル分析
前の方はメインラインに集中していますが、今はtxt 2 ctfの結果を復習します.
ctfはCNTK Text Formatの略語で、CNTK処理テキストのフォーマットです.ctfフォーマットはこのようです.
0	|S0 15:1	|S1 0:1
0	|S0 3:1	|S1 0:1
0	|S0 25:1	|S1 1:1
0	|S0 2:1	|S1 0:1
0	|S0 0:1	|S1 0:1
0	|S0 1:1	|S1 0:1
0	|S0 3:1	|S1 0:1
0	|S0 16:1	|S1 4:1
0	|S0 2:1	|S1 0:1
0	|S0 17:1	|S1 0:1
0	|S0 1:1	|S1 0:1
0	|S0 18:1	|S1 6:1
0	|S0 6:1	|S1 0:1
0	|S0 19:1	|S1 3:1
0	|S0 4:1	|S1 0:1
0	|S0 16:1	|S1 4:1
0	|S0 5:1	|S1 0:1
0	|S0 1:1	|S1 0:1
0	|S0 20:1	|S1 0:1
まず第一行を見に来ます.
0	|S0 15:1	|S1 0:1
行頭の0は1番目のファイルで、1は2番目のファイルです.私たちは2つのファイルしかありませんので、値を取るのはまず0で、後は1です.S 0はsource_ですwl、15は16行目です.私たちはsourceを見ますwlの内容:
0
;
=
let
(
)
.
{
}
Test
value
v
this
new
,

s
"s"
console
log

class
print
TestNumber
mul
a
public
:
number
constructor
extends
return
*
false
[
_UNKNOWN_
表でわかるように、対応は.
「124 S 1 0:1」は、targt_です.wlの1行目はOです.
私たちは第2の行動例で:
0	|S0 3:1	|S1 0:1
左のS 0 3:1はsource_を調べます.wl対応はletです.右のS 1 0:1は、ターゲットにあります.wlで対応するのはOです.letはキーワードで、タイプ情報がありません.
データの読みだし
reader
上のフォーマットの基本知識があります.readerのコードを見れば分かります.
def create_reader(path, is_training):
	return C.io.MinibatchSource(C.io.CTFDeserializer(path, C.io.StreamDefs(
			source		= C.io.StreamDef(field='S0', shape=vocab_size, is_sparse=True), 
			slot_labels	= C.io.StreamDef(field='S1', shape=num_labels, is_sparse=True)
	)), randomize=is_training, max_sweeps = C.io.INFINITELY_REPEAT if is_training else 1)
sourceはS 0を読んでいます.token情報です.slaotlabelsはS 1というジャンルの情報を読んでいます.shapeの形はそれぞれソース辞書とタイプ辞書のサイズです.
vocab_size = len(source_dict)
num_labels = len(target_dict)
ソレックスdictとtarget_ファイルを読み込むプロセスは以下の通りです.
files = {
	'train': { 'file': 'data/train.ctf', 'location': 0 },
	'valid': { 'file': 'data/valid.ctf', 'location': 0 },
	'test': { 'file': 'data/test.ctf', 'location': 0 },
	'source': { 'file': 'data/source_wl', 'location': 1 },
	'target': { 'file': 'data/target_wl', 'location': 1 }
}

source_wl = [line.rstrip('
'
) for line in open(files['source']['file'])] target_wl = [line.rstrip('
'
) for line in open(files['target']['file'])] source_dict = {source_wl[i]:i for i in range(len(source_wl))} target_dict = {target_wl[i]:i for i in range(len(target_wl))}
input
inputになると、S 0、S 1、0、1というラベルはもうなくて、配列になります.
	inputs = C.ops.argmax(x).eval({x: data[x]})
以下のこの二重循環は、iサイクルが第一のtsプロジェクトに対応し、jサイクルは各tokenに対応する.
	for i in range(len(inputs)):
		ts = []
		table = {}
		counts = {}
		for j in range(len(inputs[i])):
また、2つのtsプロジェクトを例にとって、inputの第1レベルは2つの要素の配列であり、ctfの第1列の0と1に対応している.
inputs[0]= [15.  3. 25.  2.  0.  1.  3. 16.  2. 17.  1.  3.  0.  2. 25. 35.  0.  1.
  3.  0.  2.  0. 35.  0.  1.  3.  0.  2.  0. 32.  0.  1. 18.  6. 19.  4.
 16.  5.  1. 20.]
inputs[1]= [15. 21.  9.  7. 26. 10. 27. 28.  1. 29.  4. 11.  5.  7. 12.  6. 10.  2.
 11.  1.  8. 22.  4.  5.  7. 18.  6. 19.  4. 12.  6. 10.  5.  1.  8. 35.
  4.  0.  5.  7. 31. 12.  6. 10. 35.  0.  1.  8.  8.  3. 35.  2. 13.  9.
  4.  0.  5.  1. 35.  6. 22.  4.  5.  1. 21. 35. 30.  9.  7. 35.  4.  0.
  5.  7. 31. 12.  6. 10. 35.  0.  1.  8.  8.  3.  0.  2. 13. 35.  4.  0.
  5.  1.  0.  6. 22.  4.  5.  1. 35. 35.  4.  0. 14.  0.  5.  7. 31.  0.
 35.  0.  1.  8. 35. 35.  7. 35. 27. 35.  1. 35. 27. 28.  1.  8. 35. 35.
  4. 35.  5.  7. 18.  6. 19.  4. 35.  6. 35.  5.  1. 18.  6. 19.  4. 35.
  6. 35.  5.  1.  8.  3.  0.  2. 33.  1.  3.  0.  2.  0.  1.  3.  0.  2.
 17.  1.  3.  0.  2. 34.  0. 14.  0. 14.  0. 14.  0. 35.  1. 20.]
例えばinputs[0][0]は15で、input[0][1]は3で、input[0][2]は25で、対応するctfの値は以下の通りです.
0	|S0 15:1	|S1 0:1
0	|S0 3:1	|S1 0:1
0	|S0 25:1	|S1 1:1
同じくinputts[1]の上位の方は15.21.9.7.26.train.ctfに対応しています.
1	|S0 15:1	|S1 0:1
1	|S0 21:1	|S1 0:1
1	|S0 9:1	|S1 2:1
1	|S0 7:1	|S1 0:1
1	|S0 26:1	|S1 0:1
エンハンスdata-隠しレイヤーを更新します.
次に上の情報を連絡して、enhanceを見ます.ダタの実現:
def enhance_data(data, enc):
	guesses = enc.eval({x: data[x]})
	inputs = C.ops.argmax(x).eval({x: data[x]})
	tables = []
	for i in range(len(inputs)):
		ts = []
		table = {}
		counts = {}
		#      token
		for j in range(len(inputs[i])):
			inp = int(inputs[i][j])
			if inp not in table:
				table[inp] = guesses[i][j]
				counts[inp] = 1
			else:
				table[inp] += guesses[i][j]
				counts[inp] += 1
		for inp in table:
			table[inp] /= counts[inp]
各tokenの前に計算されたgusess値を保存します.これらの値をまとめます.
		#      token,    ts   guess 
		for j in range(len(inputs[i])):
			inp = int(inputs[i][j])
			ts.append(table[inp])
		#          guess 
		tables.append(np.array(np.float32(ts)))
最後に、隠しレイヤーのデータを更新します.
	s = C.io.MinibatchSourceFromData(dict(t=(tables, C.layers.typing.Sequence[C.layers.typing.tensor])))
	mems = s.next_minibatch(minibatch_size)
	print('mems=',mems)
	data[t] = mems[s.streams['t']]
ここで、data[t]のtは、次のように定義されている.
t = C.sequence.input_variable(hidden_dim, name="t")
いくつかの経験とテクニック
epoch_を修正するsize
私たちはlexer.pyを実行した後、統計パラメータを出力します.
Train projects: 580
Validation projects: 72
Test projects: 73
Train files: 51431
Validation files: 4704
Test files: 3916
Producing vocabularies
Size of source vocab: 42631
Size of target vocab: 12386
Writing train/valid/test files
Overall tokens: 19286557 train, 1663181 valid and 1806291 test
これによってinfer.pyのパラメータを変更できます.
epoch_size = 19286557
node OOM問題があったらどうしますか?
適当にmax-old-space-sizeの大きさを増加して、単位はMです.例:
node --max-old-space-size=16384 GetTypes.js