-
Notifications
You must be signed in to change notification settings - Fork 9
Expand file tree
/
Copy pathProgram.fs
More file actions
167 lines (146 loc) · 6.88 KB
/
Copy pathProgram.fs
File metadata and controls
167 lines (146 loc) · 6.88 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
namespace LangRNN
open System.IO
open Argu
open Tensor.Utils
open Tensor
open Models
module Program =
type CLIArgs =
| Generate of int
| Train
| Slack of string
| TokenLimit of int
| MaxIters of int
| BatchSize of int64
| [<Mandatory>] Data of string
| Steps of int64
| Hiddens of int64
| CheckpointInterval of int
| DropState of float
| PrintSamples
| MultiStepLoss
| UseChars
with
interface IArgParserTemplate with
member s.Usage =
match s with
| Generate _ -> "generates samples from trained model using the specified seed"
| Train -> "train model"
| Slack _ -> "connect as a slack bot using the specified key"
| TokenLimit _ -> "limits the number of training tokens"
| MaxIters _ -> "limits the number of training epochs"
| BatchSize _ -> "training batch size"
| Data _ -> "path to data file"
| Steps _ -> "number of steps to back-propagate gradient for"
| Hiddens _ -> "number of hidden units"
| CheckpointInterval _ -> "number of epochs between writing checkpoint"
| DropState _ -> "probability of setting latent state to zero at the start of a mini-batch"
| PrintSamples -> "prints some samples from the training set"
| MultiStepLoss -> "use multi-step loss"
| UseChars -> "uses chars as tokens (instead of words)"
[<EntryPoint>]
let main argv =
// debug
Util.disableCrashDialog ()
//SymTensor.Compiler.Cuda.Debug.ResourceUsage <- true
//SymTensor.Compiler.Cuda.Debug.SyncAfterEachCudaCall <- true
SymTensor.Compiler.Cuda.Debug.FastKernelMath <- true
//SymTensor.Debug.VisualizeUExpr <- true
//SymTensor.Debug.TraceCompile <- true
//SymTensor.Debug.Timing <- true
//SymTensor.Compiler.Cuda.Debug.Timing <- true
//SymTensor.Compiler.Cuda.Debug.TraceCompile <- true
// required for SlackBot
Cuda.setContext ()
// tests
//verifyRNNGradientOneHot DevCuda
//verifyRNNGradientIndexed DevCuda
//TestUtils.compareTraces verifyRNNGradientIndexed false |> ignore
//exit 0
let parser = ArgumentParser.Create<CLIArgs> (helpTextMessage="Language learning RNN",
errorHandler = ProcessExiter())
let args = parser.ParseCommandLine argv
let batchSize = args.GetResult (<@BatchSize@>, 250L)
let stepsPerSmpl = args.GetResult (<@Steps@>, 25L)
let embeddingDim = args.GetResult (<@Hiddens@>, 128L)
let checkpointInterval = args.GetResult (<@CheckpointInterval@>, 10)
let dropState = args.GetResult (<@DropState@>, 0.0)
let multiStepLoss = args.Contains <@MultiStepLoss@>
// load data
let data = WordData (dataPath = args.GetResult <@Data@>,
vocSizeLimit = None,
stepsPerSmpl = stepsPerSmpl,
minSamples = int64 (float batchSize / 0.90),
tokenLimit = args.TryGetResult <@TokenLimit@>,
useChars = args.Contains <@UseChars@>)
// instantiate model
let model = GRUInst (VocSize = int64 data.VocSize,
EmbeddingDim = embeddingDim,
MultiStepLoss = multiStepLoss)
// output some training samples
if args.Contains <@PrintSamples@> then
for smpl in 0L .. 3L do
for i, s in Seq.indexed (data.Dataset.Trn.SlotBatches batchSize stepsPerSmpl) do
let words = s.Words.[smpl, *] |> data.ToStr
printfn "Batch %d, sample %d:\n%s\n" i smpl words
// train model or load checkpoint
printfn "Training with %d steps per slot" stepsPerSmpl
let trainCfg = {
Train.defaultCfg with
MinIters = Some 150
MaxIters = args.TryGetResult <@ MaxIters @>
LearningRates = [1e-2; 1e-3; 1e-4; 1e-5; 1e-6]
//LearningRates = [1e-3; 1e-4; 1e-5; 1e-6]
//LearningRates = [1e-4; 1e-5; 1e-6]
BatchSize = System.Int64.MaxValue
SlotSize = Some stepsPerSmpl
BestOn = Training
CheckpointFile = Some "LangRNN-%ITER%.h5"
CheckpointInterval = Some checkpointInterval
PerformTraining = args.Contains <@Train@>
}
model.Train data.Dataset dropState trainCfg |> ignore
// generate some word sequences
match args.TryGetResult <@Generate@> with
| Some seed ->
printfn "Generating..."
let NStart = 30
let NPred = 20
let rng = System.Random seed
let allWords = data.Words |> Array.ofList
let startIdxs = rng.Seq (0, allWords.Length-100) |> Seq.take NPred
let startWords =
startIdxs
|> Seq.map (fun startIdx ->
let mutable pos = startIdx
if not data.UseChars then
while pos+2*NStart >= allWords.Length ||
allWords.[pos+NStart-1] <> ">" ||
(allWords.[pos .. pos+NStart-1] |> Array.contains "===") do
pos <- pos + 1
if pos >= allWords.Length then pos <- 0
allWords.[pos .. pos+2*NStart-1] |> List.ofArray
)
|> Seq.map data.Tokenize
|> List.ofSeq
|> HostTensor.ofList2D
let genWords = model.Generate 1001 {Words=startWords |> CudaTensor.transfer}
let genWords = genWords.Words |> HostTensor.transfer
for s in 0 .. NPred-1 do
printfn "======================= Sample %d ====================================" s
printfn "====> prime: \n%s" (data.ToStr startWords.[int64 s, 0L .. int64 NStart-1L])
printfn "\n====> generated:\n> %s" (data.ToStr genWords.[int64 s, *])
printfn "\n====> original: \n> %s" (data.ToStr startWords.[int64 s, int64 NStart ..])
printfn ""
| None -> ()
// slack bot
match args.TryGetResult <@Slack@> with
| Some slackKey ->
let bot = SlackBot (data, model, slackKey)
printfn "\nSlackBot is connected. Press Ctrl+C to quit."
while true do
Async.Sleep 10000 |> Async.RunSynchronously
| None -> ()
// shutdown
Cuda.shutdown ()
0