nysol-mining 3.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/bin/mbopt.rb +522 -0
- data/bin/mburst.rb +716 -0
- data/bin/mgfeatures.rb +340 -0
- data/bin/mglmnet.rb +843 -0
- data/bin/mgnfeatures.rb +369 -0
- data/bin/mgpmetis.rb +449 -0
- data/bin/midxmine.rb +484 -0
- data/bin/mnb.rb +631 -0
- data/bin/mnetsimile.rb +572 -0
- data/bin/mnewman.rb +345 -0
- data/bin/msketchsort.rb +243 -0
- data/bin/msm.rb +172 -0
- data/ext/sketchsortrun/Main.cpp +161 -0
- data/ext/sketchsortrun/Main.hpp +24 -0
- data/ext/sketchsortrun/SketchSort.cpp +526 -0
- data/ext/sketchsortrun/SketchSort.hpp +138 -0
- data/ext/sketchsortrun/extconf.rb +26 -0
- data/ext/sketchsortrun/sketchsortrun.cpp +56 -0
- data/lib/nysol/mining.rb +24 -0
- metadata +89 -0
data/bin/mburst.rb
ADDED
@@ -0,0 +1,716 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# encoding:utf-8
|
3
|
+
|
4
|
+
require 'fileutils'
|
5
|
+
require 'rubygems'
|
6
|
+
require 'nysol/mcmd'
|
7
|
+
|
8
|
+
$version=1.0
|
9
|
+
$revision="###VERSION###"
|
10
|
+
|
11
|
+
def help
|
12
|
+
|
13
|
+
STDERR.puts <<EOF
|
14
|
+
----------------------------
|
15
|
+
mburst.rb version #{$version}
|
16
|
+
----------------------------
|
17
|
+
概要) HMMによるburst検知プログラム
|
18
|
+
特徴) 1) 分布のパラメータの変化を検知する
|
19
|
+
2) 確率分布としては指数分布、ポアソン分布、正規分布、二項分布に対応
|
20
|
+
書式) mburst.rb f= dist=exp|poisson|gauss|binom [s=] [p=] i= [o=] [--help]
|
21
|
+
|
22
|
+
例) mburst.rb f=interval dist=exp i=burstExp.csv o=output.csv
|
23
|
+
|
24
|
+
i= : 入力ファイル名【必須】
|
25
|
+
o= : 出力ファイル名【オプション:defaultは標準出力】
|
26
|
+
d= : デバッグ情報を出力するファイル【オプション】
|
27
|
+
dist= : 仮定する分布名称(exp:指数関数,poisson:ポアソン分布,gauss:正規分布,binom:二項分布)【必須】
|
28
|
+
f= : burst検知対象となる数値項目名(i=上の項目名)【必須】
|
29
|
+
param= : 定常状態における分布のパラメータ。注1参照【オプション】
|
30
|
+
pf= : 定常状態における分布のパラメータ項目名(i=上の項目名)注1参照【オプション】
|
31
|
+
s= : burstスケール(詳細は注2参照)【オプション:default=2.0】
|
32
|
+
p= : 同一状態遷移確率(この値を高くするとbusrtしにくくなる。詳細は注3参照)【オプション:default=0.6】
|
33
|
+
|
34
|
+
n= : dist=binomの場合の試行回数【n= or nf=いずれかを指定】
|
35
|
+
nf= : dist=binomの場合の試行回数の項目名
|
36
|
+
v= : dist=gaussの場合の分散値(指定がなければf=項目のデータから推定)
|
37
|
+
nv= : dist=gaussの場合の分散の項目名
|
38
|
+
--help : ヘルプの表示
|
39
|
+
|
40
|
+
注1) 定常状態における分布のパラメータ(母数)の与え方は以下の3通り。
|
41
|
+
1) para=で指定した値とする。
|
42
|
+
2) pf=で指定した項目の値を用いる。時刻に依存してパラメータが異なることが仮定できる場合のため。
|
43
|
+
3) para=,pf=の指定がなければ、f=で指定した値から自動的に計算される。
|
44
|
+
|
45
|
+
注2) 定常状態、burst状態における分布パラメータの計算方法は以下のとおり。
|
46
|
+
S: s=で指定した値、n:データ件数、x_i: f=でしていした項目のi行目の値
|
47
|
+
exp: 確率密度関数f(x)=λ*exp(-λx)、パラメータはλ(平均イベント発生回数)
|
48
|
+
定常(state0)状態λ0=n/Σx_i
|
49
|
+
burst(state1)状態λ1=λ0*S
|
50
|
+
poisson: 確率関数f(x)=λ^x*exp(-λ)/x!、パラメータはλ(平均イベント発生回数)
|
51
|
+
定常(state0)状態λ0=Σx_i/n
|
52
|
+
burst(state1)状態λ1=λ0*S
|
53
|
+
gauss: 確率密度関数: f(x)= 1/√2πσ^2 exp(-(x-μ)^2/2σ^2)、パラメータはμ(平均)
|
54
|
+
m=Σx_i/n、v=Σ(x_i-m)^2/nとすると、
|
55
|
+
下側burst(state-)状態μ- =m-sqrt(v)*S
|
56
|
+
定常(state0)状態μ0 =m
|
57
|
+
上側burst(state+)状態μ+ =m+sqrt(v)*S
|
58
|
+
binom: 確率関数: f(x)=(T choose x)p^x(1-p)^(T-x):パラメータはp(成功確率)
|
59
|
+
定常(state0)状態p0=(Σx_i/n)/T (平均成功回数/試行回数)
|
60
|
+
burst(state1)状態p1=S/((1-p0)/p0+S)
|
61
|
+
|
62
|
+
注3) 状態遷移確率の設定方法。
|
63
|
+
p: p=で指定した値
|
64
|
+
exp, poisson, binom:
|
65
|
+
prob(state0→state0)=prob(state1→state1)
|
66
|
+
prob(state0→state1)=prob(state1→state0)=1-p
|
67
|
+
gauss:
|
68
|
+
prob(state-1→state-1)=prob(state0→state0)=prob(state1→state1)=p
|
69
|
+
prob(state0→state-1)=prob(state0→state1)=prob(state2→state2)=(1-p)/2
|
70
|
+
prob(state-1→state0)=prob(state1→state0)=(1-p)/3*2
|
71
|
+
prob(state-1→state1)=prob(state1→state-1)=(1-p)/3
|
72
|
+
|
73
|
+
Copyright(c) NYSOL 2012- All Rights Reserved.
|
74
|
+
EOF
|
75
|
+
exit
|
76
|
+
end
|
77
|
+
|
78
|
+
def ver()
|
79
|
+
$revision ="0" if $revision =~ /VERSION/
|
80
|
+
STDERR.puts "version #{$version} revision #{$revision}"
|
81
|
+
exit
|
82
|
+
end
|
83
|
+
|
84
|
+
|
85
|
+
|
86
|
+
|
87
|
+
help() if ARGV.size <= 0
|
88
|
+
help() if ARGV[0]=="--help"
|
89
|
+
ver() if ARGV[0]=="--version"
|
90
|
+
|
91
|
+
# パラメータ設定
|
92
|
+
args=MCMD::Margs.new(ARGV,"i=,o=,d=,f=,dist=,s=,p=,pf=,n=,nf=,v=,vf=,param=","i=,o=,f=,dist=")
|
93
|
+
|
94
|
+
iFile = args.file("i=","r")
|
95
|
+
dFile = args.file("d=","w",nil)
|
96
|
+
oFile = args.file("o=","w")
|
97
|
+
fName = args.field("f=",iFile)
|
98
|
+
fName = fName["names"].join(",") if fName
|
99
|
+
pName = args.field("pf=",iFile)
|
100
|
+
pName = pName["names"].join(",") if pName
|
101
|
+
nName = args.field("nf=",iFile)
|
102
|
+
nName = nName["names"].join(",") if nName
|
103
|
+
vName = args.field("vf=",iFile)
|
104
|
+
vName = vName["names"].join(",") if vName
|
105
|
+
|
106
|
+
distType = args.str("dist=")
|
107
|
+
unless ["exp","poisson","gauss","binom"].index(distType)
|
108
|
+
raise "`dist=' takes `exp',`poisson',`gauss' or `binom'"
|
109
|
+
end
|
110
|
+
|
111
|
+
burstScale = args.float("s=",2.0)
|
112
|
+
iProb = args.float("p=",0.6)
|
113
|
+
trial = args.float("n=")
|
114
|
+
var = args.float("v=")
|
115
|
+
param = args.float("param=")
|
116
|
+
|
117
|
+
if distType!="binom" and (trial or nName)
|
118
|
+
raise "`n=' or `nf=' is a parameter for binom burst."
|
119
|
+
end
|
120
|
+
|
121
|
+
if distType!="gauss" and (var or vName)
|
122
|
+
raise "`v=' or `vf=' is a parameter for gauss burst."
|
123
|
+
end
|
124
|
+
|
125
|
+
if distType=="binom"
|
126
|
+
if trial==nil and nName==nil
|
127
|
+
raise "`n=' or `nf=' have to be specified in binom burst."
|
128
|
+
end
|
129
|
+
if nName!=nil and not (param or pName)
|
130
|
+
raise "`param=' or `pf=' have to be specified with `nf=' in binom burst."
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
if distType=="gauss"
|
135
|
+
if (param!=nil and var==nil) or (param==nil and var!=nil)
|
136
|
+
raise "`param=' and `var=' have to be specified together in gaussian burst."
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
##########################
|
141
|
+
module MDM
|
142
|
+
|
143
|
+
class DistBurst
|
144
|
+
attr_reader :data
|
145
|
+
attr_reader :burstSymbol
|
146
|
+
|
147
|
+
def initialize(name)
|
148
|
+
@name=name
|
149
|
+
@data=[]
|
150
|
+
@dpar=nil
|
151
|
+
@dpar=[] if @parFld
|
152
|
+
# 入力ファイルを項目別にメモリにセット
|
153
|
+
MCMD::Mcsvin.new("i=#{@fname}"){|csv|
|
154
|
+
csv.each{|flds|
|
155
|
+
v=flds[@valFld].to_f
|
156
|
+
p=flds[@parFld].to_f if @parFld
|
157
|
+
@data << v
|
158
|
+
@dpar << p if @parFld
|
159
|
+
}
|
160
|
+
}
|
161
|
+
# burst項目の出力シンボル。
|
162
|
+
# 状態0と状態1をburst項目として0,1として出力。
|
163
|
+
# このシンボル表を変更するのであれば継承クラスで独自に定義する。
|
164
|
+
@burstSymbol=["0","1"]
|
165
|
+
end
|
166
|
+
|
167
|
+
# 初期確率
|
168
|
+
# 2状態の確率分布のみ対応。それ以外は継承クラスで独自に定義する。
|
169
|
+
def initProbLn()
|
170
|
+
initProbLn=[ln(1.0), ln(0.0)]
|
171
|
+
return initProbLn
|
172
|
+
end
|
173
|
+
|
174
|
+
# 遷移確率
|
175
|
+
# 2状態の遷移確率のみ対応。それ以外は継承クラスで独自に定義する。
|
176
|
+
# to
|
177
|
+
# 0 1
|
178
|
+
# from 0 transProbLn[0][0] transProbLn[0][1]
|
179
|
+
# 1 transProbLn[1][0] transProbLn[1][1]
|
180
|
+
def calTransProbLn(inertiaProb)
|
181
|
+
transProbLn=[]
|
182
|
+
transProbLn << [ln( inertiaProb), ln(1.0-inertiaProb)]
|
183
|
+
transProbLn << [ln(1.0-inertiaProb), ln( inertiaProb)]
|
184
|
+
return transProbLn
|
185
|
+
end
|
186
|
+
|
187
|
+
# 自然対数の計算(ln(0)=-9999.0で定義
|
188
|
+
def ln(prob)
|
189
|
+
ret=-9999.0
|
190
|
+
if prob>0
|
191
|
+
ret=Math::log(prob)
|
192
|
+
end
|
193
|
+
return ret
|
194
|
+
end
|
195
|
+
|
196
|
+
def logsum(from,to)
|
197
|
+
sum=0.0
|
198
|
+
(from.to_i..to.to_i).each{|x|
|
199
|
+
sum+=Math::log(x)
|
200
|
+
}
|
201
|
+
return sum
|
202
|
+
end
|
203
|
+
|
204
|
+
def show(fpw=STDERR)
|
205
|
+
fpw.puts "### MDM::DistBurst class"
|
206
|
+
fpw.puts " 入力: #{@fname}, 値項目名:#{@valFld}"
|
207
|
+
fpw.puts " 確率(密度)関数名:#{@name}"
|
208
|
+
fpw.puts " データ件数: #{@data.size}"
|
209
|
+
fpw.puts " @data=#{@data.join(',')}"
|
210
|
+
end
|
211
|
+
end
|
212
|
+
|
213
|
+
#-----------------------------------------------------------
|
214
|
+
# 指数分布(事象発生間隔分布)
|
215
|
+
# λ: 時間あたりの事象の平均発生回数
|
216
|
+
# x: 事象の発生間隔
|
217
|
+
# f(x)=λe^{-λx}
|
218
|
+
class ExpBurst < DistBurst
|
219
|
+
def initialize(fname,valFld,parFld,param)
|
220
|
+
@fname =fname
|
221
|
+
@valFld =valFld
|
222
|
+
@parFld =parFld
|
223
|
+
@param =param
|
224
|
+
super("exp")
|
225
|
+
|
226
|
+
# パラメータのセット
|
227
|
+
# 定常状態平均到着数
|
228
|
+
@term=0.0
|
229
|
+
@data.each{|v| @term+=v}
|
230
|
+
|
231
|
+
unless @parFld
|
232
|
+
if @param!=nil
|
233
|
+
@lamda=param
|
234
|
+
else
|
235
|
+
@lamda=@data.size.to_f/@term
|
236
|
+
end
|
237
|
+
end
|
238
|
+
end
|
239
|
+
|
240
|
+
# 指数分布の確率密度関数: f(x)=λexp(-λx)
|
241
|
+
# log f(x) = logλ - λx
|
242
|
+
def probFunc(x,lamda)
|
243
|
+
return Math::log(lamda) - lamda*x
|
244
|
+
end
|
245
|
+
|
246
|
+
def stateProbLn(burstScale)
|
247
|
+
@burstScale=burstScale
|
248
|
+
stateProbLn=[]
|
249
|
+
(0...@data.size).each{|i|
|
250
|
+
x=@data[i]
|
251
|
+
p=nil
|
252
|
+
if @dpar
|
253
|
+
p=@dpar[i]
|
254
|
+
else
|
255
|
+
p=@lamda
|
256
|
+
end
|
257
|
+
stateProbLn << [ probFunc(x,p), probFunc(x,p*@burstScale) ]
|
258
|
+
}
|
259
|
+
return stateProbLn
|
260
|
+
end
|
261
|
+
|
262
|
+
def show(fpw=STDERR)
|
263
|
+
super(fpw)
|
264
|
+
fpw.puts "### MDM::ExpBurst < DistBurst class"
|
265
|
+
fpw.puts " @lamda: #{@lamda}, @param: #{@param}"
|
266
|
+
fpw.puts " @dpar: #{@dpar}"
|
267
|
+
fpw.puts " @term : #{@term}"
|
268
|
+
end
|
269
|
+
end
|
270
|
+
|
271
|
+
#-----------------------------------------------------------
|
272
|
+
# ポアソン分布(事象発生数分布)
|
273
|
+
# λ: 時間あたりの事象の平均発生回数
|
274
|
+
# x: 事象の発生間隔
|
275
|
+
# 確率関数: f(x)=λ^x*exp(-λ)/x!
|
276
|
+
class PoissonBurst < DistBurst
|
277
|
+
def initialize(fname,valFld,parFld,param)
|
278
|
+
@fname =fname
|
279
|
+
@valFld =valFld
|
280
|
+
@parFld =parFld
|
281
|
+
@param =param
|
282
|
+
super("poisson")
|
283
|
+
|
284
|
+
# パラメータのセット
|
285
|
+
# 定常状態平均到着数
|
286
|
+
@count=0.0
|
287
|
+
@data.each{|v| @count+=v}
|
288
|
+
|
289
|
+
unless @parFld
|
290
|
+
if @param!=nil
|
291
|
+
@lamda=param
|
292
|
+
else
|
293
|
+
@lamda=@count/@data.size.to_f
|
294
|
+
end
|
295
|
+
end
|
296
|
+
end
|
297
|
+
|
298
|
+
# ポアソン分布の確率関数
|
299
|
+
# f(x)=λ^x/x!*exp(-λ)
|
300
|
+
# log f(x) = x*logλ-λ-Σ_{i=1..x}i
|
301
|
+
def probFunc(x,lamda)
|
302
|
+
if x==0 # 0!=1のため
|
303
|
+
return -lamda
|
304
|
+
else
|
305
|
+
return x*Math::log(lamda) - Math::log((1.0+x)*x/2.0) - lamda
|
306
|
+
end
|
307
|
+
end
|
308
|
+
|
309
|
+
def stateProbLn(burstScale)
|
310
|
+
@burstScale=burstScale
|
311
|
+
stateProbLn=[]
|
312
|
+
(0...@data.size).each{|i|
|
313
|
+
x=@data[i]
|
314
|
+
p=nil
|
315
|
+
if @dpar
|
316
|
+
p=@dpar[i]
|
317
|
+
else
|
318
|
+
p=@lamda
|
319
|
+
end
|
320
|
+
stateProbLn << [ probFunc(x,p), probFunc(x,p*@burstScale) ]
|
321
|
+
}
|
322
|
+
return stateProbLn
|
323
|
+
end
|
324
|
+
|
325
|
+
def show(fpw=STDERR)
|
326
|
+
super(fpw)
|
327
|
+
fpw.puts "### MDM::PoissonBurst < DistBurst class"
|
328
|
+
fpw.puts " @lamda: #{@lamda}, @param: #{@param}"
|
329
|
+
fpw.puts " @dpar: #{@dpar}"
|
330
|
+
fpw.puts " @count: #{@count}"
|
331
|
+
end
|
332
|
+
end
|
333
|
+
|
334
|
+
#-----------------------------------------------------------
|
335
|
+
# 正規分布(誤差分布)
|
336
|
+
# mean: 平均
|
337
|
+
# var: 分散
|
338
|
+
# 確率密度関数: f(x)= 1/√2πσ^2 exp(-(x-μ)^2/2σ^2
|
339
|
+
class GaussBurst < DistBurst
|
340
|
+
def initialize(fname,valFld,parFld,param,varFld,var)
|
341
|
+
@fname =fname
|
342
|
+
@valFld =valFld
|
343
|
+
@parFld =parFld
|
344
|
+
@param =param
|
345
|
+
super("gauss")
|
346
|
+
|
347
|
+
# パラメータのセット
|
348
|
+
# 定常状態平均値と不偏分散
|
349
|
+
@mean=nil
|
350
|
+
@var=nil
|
351
|
+
if @parFld
|
352
|
+
@var=[]
|
353
|
+
# 分散項目読み込み
|
354
|
+
MCMD::Mcsvin.new("i=#{@fname}"){|csv|
|
355
|
+
csv.each{|flds|
|
356
|
+
v=flds[varFld].to_f
|
357
|
+
@var << v
|
358
|
+
}
|
359
|
+
}
|
360
|
+
else
|
361
|
+
if @param!=nil
|
362
|
+
@mean=@param
|
363
|
+
@var=var
|
364
|
+
else
|
365
|
+
@mean=0.0
|
366
|
+
@var=0.0
|
367
|
+
@data.each{|v| @mean+=v}
|
368
|
+
@mean/=@data.size.to_f
|
369
|
+
@data.each{|v| @var+=(v-@mean)**2}
|
370
|
+
@var/=(@data.size-1).to_f
|
371
|
+
end
|
372
|
+
end
|
373
|
+
|
374
|
+
# gauss分布burstでは、状態0,1,2を-1,0,1で出力
|
375
|
+
@burstSymbol=["-1","0","1"]
|
376
|
+
end
|
377
|
+
|
378
|
+
# 初期確率
|
379
|
+
def initProbLn()
|
380
|
+
initProbLn=[ln(0.0), ln(1.0), ln(0.0)]
|
381
|
+
return initProbLn
|
382
|
+
end
|
383
|
+
|
384
|
+
# 遷移確率
|
385
|
+
# to
|
386
|
+
# - 0 +
|
387
|
+
# - transProbLn[0][0] transProbLn[0][1] transProbLn[0][2]
|
388
|
+
# from 0 transProbLn[1][0] transProbLn[1][1] transProbLn[1][2]
|
389
|
+
# + transProbLn[2][0] transProbLn[2][1] transProbLn[2][2]
|
390
|
+
def calTransProbLn(inertiaProb)
|
391
|
+
transProbLn=[]
|
392
|
+
transProbLn << [ln( inertiaProb ), ln((1.0-inertiaProb)/3.0*2.0), ln((1.0-inertiaProb)/3.0)]
|
393
|
+
transProbLn << [ln((1.0-inertiaProb)/2.0), ln( inertiaProb ), ln((1.0-inertiaProb)/2.0)]
|
394
|
+
transProbLn << [ln((1.0-inertiaProb)/3.0), ln((1.0-inertiaProb)/3.0*2.0), ln( inertiaProb )]
|
395
|
+
return transProbLn
|
396
|
+
end
|
397
|
+
|
398
|
+
# 正規分布の確率密度関数
|
399
|
+
# f(x)= 1/√2πσ^2 exp(-(x-μ)^2/2σ^2
|
400
|
+
# log f(x) = log1 - (1/2)log(2πσ^2) - (x-u)^2/2σ^2
|
401
|
+
def probFunc(x, mu, sigma2)
|
402
|
+
return Math.log(1.0)-Math.log(2.0*Math::PI*sigma2)/2.0-((x-mu)**2.0)/(2.0*sigma2)
|
403
|
+
end
|
404
|
+
|
405
|
+
def stateProbLn(burstScale)
|
406
|
+
@burstScale=burstScale
|
407
|
+
stateProbLn=[]
|
408
|
+
(0...@data.size).each{|i|
|
409
|
+
x=@data[i]
|
410
|
+
p=nil
|
411
|
+
if @dpar
|
412
|
+
p=@dpar[i]
|
413
|
+
v=@var[i]
|
414
|
+
else
|
415
|
+
p=@mean
|
416
|
+
v=@var
|
417
|
+
end
|
418
|
+
stateProbLn << [ probFunc(x,p-Math.sqrt(v)*burstScale,v), probFunc(x,p,v), probFunc(x,p+Math.sqrt(v)*burstScale,v)]
|
419
|
+
}
|
420
|
+
return stateProbLn
|
421
|
+
end
|
422
|
+
|
423
|
+
def show(fpw=STDERR)
|
424
|
+
super(fpw)
|
425
|
+
fpw.puts "### MDM::GaussBurst < DistBurst class"
|
426
|
+
fpw.puts " @mean: #{@mean}, @param: #{@param}"
|
427
|
+
fpw.puts " @dpar: #{@dpar}"
|
428
|
+
fpw.puts " @var: #{@var}"
|
429
|
+
end
|
430
|
+
end
|
431
|
+
|
432
|
+
#-----------------------------------------------------------
|
433
|
+
# 二項分布(成功数分布)
|
434
|
+
# p: 成功確率
|
435
|
+
# x: 成功回数
|
436
|
+
# 確率関数: f(x)=nCx*p^x*(1-p)^(n-x)
|
437
|
+
class BinomBurst < DistBurst
|
438
|
+
def initialize(fname,valFld,parFld,param,tryFld,trial)
|
439
|
+
@fname =fname
|
440
|
+
@valFld =valFld
|
441
|
+
@parFld =parFld
|
442
|
+
@param =param
|
443
|
+
super("binom")
|
444
|
+
|
445
|
+
# パラメータのセット
|
446
|
+
# 定常状態平均成功数
|
447
|
+
|
448
|
+
@trial=nil
|
449
|
+
if tryFld
|
450
|
+
@trial=[]
|
451
|
+
MCMD::Mcsvin.new("i=#{@fname}"){|csv|
|
452
|
+
csv.each{|flds|
|
453
|
+
v=flds[tryFld].to_f
|
454
|
+
@trial << v
|
455
|
+
}
|
456
|
+
}
|
457
|
+
else
|
458
|
+
@trial=trial.to_f
|
459
|
+
end
|
460
|
+
|
461
|
+
@prob =nil
|
462
|
+
unless @parFld
|
463
|
+
if @param!=nil
|
464
|
+
@prob=param
|
465
|
+
else
|
466
|
+
avg=0.0
|
467
|
+
@data.each{|v| avg+=v}
|
468
|
+
avg=avg/@data.size.to_f
|
469
|
+
@prob=avg/@trial
|
470
|
+
end
|
471
|
+
end
|
472
|
+
end
|
473
|
+
|
474
|
+
# 二項分布の確率関数
|
475
|
+
# f(x)=nCx*p^x*(1-p)^(n-x)
|
476
|
+
# log f(x) = Σ_{i=n..n-x+1}log(i) - Σ_{i=x..1}log(i) + x*log(p) + (n-x)*log(1-p)
|
477
|
+
def probFunc(x,prob,trial)
|
478
|
+
return logsum(trial-x+1,trial) - logsum(1,x) + x*Math::log(prob)+(trial-x)*Math::log(1-prob)
|
479
|
+
end
|
480
|
+
|
481
|
+
def stateProbLn(burstScale)
|
482
|
+
@burstScale=burstScale
|
483
|
+
stateProbLn=[]
|
484
|
+
(0...@data.size).each{|i|
|
485
|
+
x=@data[i]
|
486
|
+
p=nil
|
487
|
+
if @dpar
|
488
|
+
p=@dpar[i]
|
489
|
+
else
|
490
|
+
p=@prob
|
491
|
+
end
|
492
|
+
if @trial.class.name=="Array"
|
493
|
+
n=@trial[i]
|
494
|
+
else
|
495
|
+
n=@trial
|
496
|
+
end
|
497
|
+
stateProbLn << [ probFunc(x,p,n), probFunc(x,@burstScale/((1.0-p)/p+@burstScale),n) ]
|
498
|
+
}
|
499
|
+
return stateProbLn
|
500
|
+
end
|
501
|
+
|
502
|
+
def show(fpw=STDERR)
|
503
|
+
super(fpw)
|
504
|
+
fpw.puts "### MDM::BinomBurst < DistBurst class"
|
505
|
+
fpw.puts " @prob: #{@mean}, @param: #{@param}"
|
506
|
+
fpw.puts " @dpar: #{@dpar}"
|
507
|
+
fpw.puts " @trial: #{@trial}"
|
508
|
+
end
|
509
|
+
end
|
510
|
+
|
511
|
+
|
512
|
+
#########################################################
|
513
|
+
# バーストクラス
|
514
|
+
#########################################################
|
515
|
+
class Burst
|
516
|
+
|
517
|
+
private
|
518
|
+
|
519
|
+
def initialize(dist)
|
520
|
+
@time=[] # メッセージの到着時刻
|
521
|
+
@interval=[] # メッセージの到着間隔(指数分布burstでのみ利用)
|
522
|
+
@count=[] # メッセージの到着件数(ポアソン分布burstでのみ利用)
|
523
|
+
@dist=dist # 分布オブジェクト(PoissonBurst, ExpBurst, GaussBurst, BinomBurst)
|
524
|
+
@stateSize = @dist.initProbLn().size # 状態数
|
525
|
+
@dataSize = @dist.data.size # 状態数
|
526
|
+
end
|
527
|
+
|
528
|
+
# ###############################
|
529
|
+
# 二次元配列の確保
|
530
|
+
def array2dim(rowSize,colSize)
|
531
|
+
array=Array.new(rowSize)
|
532
|
+
(0...rowSize).each{|i|
|
533
|
+
array[i] = Array.new(colSize)
|
534
|
+
}
|
535
|
+
return array
|
536
|
+
end
|
537
|
+
|
538
|
+
# ###############################
|
539
|
+
# 全stateからtargetStateへの尤度を計算し、最大尤度と最大尤度を達成するfrom state番号を返す。
|
540
|
+
def getMaxLike(targetState,prevLike,trans,prob)
|
541
|
+
maxLike=-99999999.0
|
542
|
+
maxFrom=nil
|
543
|
+
(0...@stateSize).each{|from|
|
544
|
+
#puts "from=#{from} prevLike[from]=#{prevLike[from]} trans[from][targetState]=#{trans[from][targetState]} prob[targetState]=#{prob[targetState]}"
|
545
|
+
# 時刻t-1における尤度+log(遷移確率)+log(状態確率)
|
546
|
+
like=prevLike[from]+trans[from][targetState]+prob[targetState]
|
547
|
+
if maxLike<like
|
548
|
+
maxLike=like
|
549
|
+
maxFrom=from
|
550
|
+
end
|
551
|
+
}
|
552
|
+
#puts "maxLike=#{maxLike} maxFrom=#{maxFrom}"
|
553
|
+
return maxLike,maxFrom
|
554
|
+
end
|
555
|
+
|
556
|
+
# ###############################
|
557
|
+
# viterbi forwardアルゴリズム
|
558
|
+
# initProbLn : 初期状態確率
|
559
|
+
# stateProbLn: 状態確率
|
560
|
+
# transProbLn: 状態遷移確率
|
561
|
+
def viterbi_fwd(initProbLn, stateProbLn, transProbLn)
|
562
|
+
|
563
|
+
# 各stateでの最小コストtransitionの計算実行
|
564
|
+
like =array2dim(@dataSize+1,@stateSize)
|
565
|
+
from =array2dim(@dataSize ,@stateSize)
|
566
|
+
|
567
|
+
# 初期状態セット
|
568
|
+
(0...@stateSize).each{|state|
|
569
|
+
like[0][state]=initProbLn[state]
|
570
|
+
}
|
571
|
+
|
572
|
+
# 初期状態が0なので1から始まる
|
573
|
+
(1..@dataSize).each{|t|
|
574
|
+
(0...@stateSize).each{|state|
|
575
|
+
# tは1から始まるのでfromと@stateProbLnはt-1となる: likeのみ0要素を持つ
|
576
|
+
like[t][state],from[t-1][state] = getMaxLike( state, like[t-1], @transProbLn, @stateProbLn[t-1])
|
577
|
+
}
|
578
|
+
}
|
579
|
+
return like,from
|
580
|
+
end
|
581
|
+
|
582
|
+
def getMaxState(like)
|
583
|
+
maxLike=-99999999.0
|
584
|
+
maxState=nil
|
585
|
+
(0...@stateSize).each{|state|
|
586
|
+
if maxLike<like[state]
|
587
|
+
maxLike=like[state]
|
588
|
+
maxState=state
|
589
|
+
end
|
590
|
+
}
|
591
|
+
maxState
|
592
|
+
end
|
593
|
+
|
594
|
+
# ###############################
|
595
|
+
# viterbi backwordアルゴリズム
|
596
|
+
def viterbi_bwd(like,from)
|
597
|
+
state=Array.new(@dataSize)
|
598
|
+
|
599
|
+
# 最終時刻における尤度最大のstate
|
600
|
+
state[@dataSize-1]=getMaxState(like.last)
|
601
|
+
(@dataSize-1).step(1,-1){|t|
|
602
|
+
state[t-1]=from[t][state[t]]
|
603
|
+
}
|
604
|
+
return state
|
605
|
+
end
|
606
|
+
|
607
|
+
public
|
608
|
+
|
609
|
+
def detect(inertiaProb,burstScale)
|
610
|
+
@burstScale = burstScale # burst状態のパラメータのスケールリング
|
611
|
+
@inertiaProb = inertiaProb # 同じ状態への遷移確率
|
612
|
+
|
613
|
+
# 初期状態ベクトル(状態数)の取得
|
614
|
+
@initProbLn=@dist.initProbLn()
|
615
|
+
|
616
|
+
# 状態確率行列(データ数×状態数)の取得
|
617
|
+
@stateProbLn=@dist.stateProbLn(@burstScale)
|
618
|
+
|
619
|
+
# 状態遷移行列(状態数×状態数)の取得
|
620
|
+
@transProbLn=@dist.calTransProbLn(@inertiaProb)
|
621
|
+
|
622
|
+
# viterbiアルゴリズムforward実行
|
623
|
+
@lLikely,@from=viterbi_fwd(@initProbLn,@stateProbLn,@transProbLn)
|
624
|
+
|
625
|
+
# viterbiアルゴリズムbackward実行
|
626
|
+
@state=viterbi_bwd(@lLikely,@from)
|
627
|
+
end
|
628
|
+
|
629
|
+
# CSVによる出力
|
630
|
+
# 入力データの末尾にburst項目を追加して出力
|
631
|
+
def output(iFile,oFile)
|
632
|
+
MCMD::Mcsvin.new("i=#{iFile} -array"){|iCsv|
|
633
|
+
File.open(oFile,"w"){|fpw|
|
634
|
+
fpw.puts "#{iCsv.names.join(',')},burst"
|
635
|
+
i=0
|
636
|
+
iCsv.each{|flds|
|
637
|
+
fpw.puts "#{flds.join(',')},#{@dist.burstSymbol[@state[i]]}"
|
638
|
+
i+=1
|
639
|
+
}
|
640
|
+
}
|
641
|
+
}
|
642
|
+
end
|
643
|
+
|
644
|
+
# debug出力
|
645
|
+
def show(fpw=STDERR)
|
646
|
+
fpw.puts "### MDM::Burst class"
|
647
|
+
fpw.puts " @burstScale: #{@burstScale}"
|
648
|
+
fpw.puts " log(初期状態確率):"
|
649
|
+
(0...@stateSize).each{|i|
|
650
|
+
fpw.puts " @initProbLn[#{i}]: #{@initProbLn[i]}"
|
651
|
+
}
|
652
|
+
fpw.puts " log(状態遷移確率): @inertiaProb: #{@inertiaProb}"
|
653
|
+
(0...@stateSize).each{|i|
|
654
|
+
(0...@stateSize).each{|j|
|
655
|
+
fpw.puts " @transProbLn[#{i}][#{j}]: #{@transProbLn[i][j]}"
|
656
|
+
@transProbLn
|
657
|
+
}
|
658
|
+
}
|
659
|
+
|
660
|
+
# 項目名表示
|
661
|
+
fpw.print ""
|
662
|
+
fpw.print " t\t"
|
663
|
+
fpw.print " val\t"
|
664
|
+
(0...@stateSize).each{|state| fpw.print "probLn#{state}\t"}
|
665
|
+
(0...@stateSize).each{|state| fpw.print "likeLn#{state}\t"}
|
666
|
+
(0...@stateSize).each{|state| fpw.print " from#{state}\t"}
|
667
|
+
fpw.print " state\t"
|
668
|
+
fpw.puts ""
|
669
|
+
|
670
|
+
# 初期尤度表示
|
671
|
+
(0...@stateSize+2).each{|i| fpw.print "\t"}
|
672
|
+
(0...@stateSize).each{|state| fpw.print sprintf("%7.1f\t",@lLikely[0][state])}
|
673
|
+
fpw.puts ""
|
674
|
+
|
675
|
+
# 期別尤度表示
|
676
|
+
(0...@dataSize).each{|i|
|
677
|
+
data =@dist.data[i]
|
678
|
+
stateProbLN=@stateProbLn[i]
|
679
|
+
lLikely=@lLikely[i+1]
|
680
|
+
from=@from[i]
|
681
|
+
|
682
|
+
fpw.print sprintf("%4d\t",i)
|
683
|
+
fpw.print sprintf("%7.3f\t",data)
|
684
|
+
(0...@stateSize).each{|state| fpw.print sprintf("%7.3f\t",stateProbLN[state])}
|
685
|
+
(0...@stateSize).each{|state| fpw.print sprintf("%7.3f\t",lLikely[state])}
|
686
|
+
(0...@stateSize).each{|state| fpw.print sprintf("%7d\t",from[state])}
|
687
|
+
fpw.print sprintf("%7s\t",@dist.burstSymbol[@state[i]])
|
688
|
+
fpw.print "\n"
|
689
|
+
}
|
690
|
+
end
|
691
|
+
|
692
|
+
end # class end
|
693
|
+
|
694
|
+
########################## Module end
|
695
|
+
end
|
696
|
+
|
697
|
+
if distType=="exp"
|
698
|
+
dist=MDM::ExpBurst.new(iFile, fName, pName, param)
|
699
|
+
elsif distType=="poisson"
|
700
|
+
dist=MDM::PoissonBurst.new(iFile, fName, pName, param)
|
701
|
+
elsif distType=="gauss"
|
702
|
+
dist=MDM::GaussBurst.new(iFile, fName, pName, param, vName, var)
|
703
|
+
elsif distType=="binom"
|
704
|
+
dist=MDM::BinomBurst.new(iFile, fName, pName, param, nName, trial)
|
705
|
+
end
|
706
|
+
|
707
|
+
burst=MDM::Burst.new(dist)
|
708
|
+
burst.detect(iProb, burstScale)
|
709
|
+
burst.output(iFile,oFile)
|
710
|
+
if dFile
|
711
|
+
File.open(dFile,"w"){|fpw|
|
712
|
+
dist.show(fpw)
|
713
|
+
burst.show(fpw)
|
714
|
+
}
|
715
|
+
end
|
716
|
+
|