如何使用WinBugs做贝叶斯统计

如何使用WinBugs做贝叶斯统计,第1张

1. 点选 图示,进入WinBugs,开启 (1)新的程式编辑视窗or (2)已存在的程式功能表列:File-New 功能表列:File-Open

2. 撰写程式:程式包含三部份.

(1) Model:建构贝氏统计模式,设定各参数的prior distribution及各参数间的关系等.

(2) Data:以list指令起始,列出各参数的样本观察值及样本个数(N= ).

(3) Initial value:同样运用list指令,列出各参数的起始值.

ps:上述三大部份的程式撰写顺序并不会影响程式执行结果

例:Seeds: random effects logistic regression (下图为WinBugs Examples中Seeds的例子)

Model:

ri ~ Binomial(pi, ni)

logit(pi) = α0 + α1x1i + α2x2i + α12x1ix2i + bi

bi ~ Normal(0, τ)

在功能表列选取File → Save as 即可将程式储存於指定的档案夹内

这是状态列

Initial value

Data

Bayesian model

Prior distribution的设定

3. 执行程式

Step 1 在功能表列中点选:Model → Specification,开启Specification Tool 视窗

Step 2 Check model:

选取Model程式中的关键字"model ",按下Specification Tool视窗的check model

键,若此部份程式的语法及定义无误,则:

(1) Specification Tool 视窗的 compile 及 load data 键将会浮现,即可供执行

点选;

(2) WinBugs左下角的状态列将会显示'model is syntactically correct'

Step 3 Load data:

选取Data程式中的关键字" list ",按下Specification Tool视窗的 load data 键

若资料型式无误,则WinBugs左下角的状态列将会显示' data loaded '

可选择一次simulate数个chains

Step 4 Compile Model:

直接按下Specification Tool视窗的 compile 键,若程式无误,则WinBugs左

下角的状态列将会显示' model compiled '

Step 5 Load initial values:

选取Initial value程式中的关键字" list ",按下 load inits 键,若WinBugs

左下角的状态列显示:

(1) ' initial values loaded: model initialized ' 表示资料型式无误,接续Step6.

(2) ' initial values loaded: model contains uninitialized nodes ' 若程式没有缺

漏,会出现这样的讯息,则有两种可能:

(Ⅰ) 当只simulate一个chain时,出现上述的讯息表示程式中尚有一些参数

还未定义起始值,会发生这样的状况,有时是因为未提供起始值之参数

(如Seeds例子中的:sigma) 与其他参数间 (如:tau) 具有函数对应关

系,(如:sigma <- 1 / sqrt(tau));在此情况下,须再按下 gen inits 键,

让WinBugs依参数间的对应关系,自动为剩馀未定义起始值的参数生

成一个起始值,执行後,WinBugs左下角的状态列将会显示' initial

values generated: model initialized '.

(Ⅱ) 当simulate 两个以上的chains时,这个讯息代表至少有一个chains 的

参数尚未定义起始值同样地,亦可按下 gen inits 键,自动生成起

始值,或者回到程式,自行定义起始值.

Step 6 关闭Specification Tool视窗

4. Monitor 感兴趣的参数

Step 1 在功能表列中点选:Inference → Samples,开启Sample Monitor Tool 视窗

Step 2 在node方块中输入想要monitor的参数,如:在Seeds范例中,欲generate posterior

samples的参数为:alpha0,alpha1,alpha2,alpha12,tau,sigma,此步骤便是

在node方块中输入这些参数名称,每输入一个参数名称,便按一次 set 键,

待完全键入後,关闭此视窗.

ps:由於此步骤之作用仅在monitor参数,视窗中之beg,end,thin或chains皆

不会有任何作用,亦即更改其中的数值皆不会对output有任何影响,在此先

省略不谈,之後在simulated value时将会对这些指令之功用提出简略的说明.

……

5. Update the Model

Step 1 在功能表列中点选:Model → Update,开启Update Tool 视窗

Step 2 在update方块中键入想要generate posterior samples的样本数,如:3000笔,按

下 update 键,则iteration将由0 run 至3000,WinBugs左下角的状态列将会

显示generate posterior samples所需的时间,如:' updates took 1 s ',执行完後

关闭Update Tool 视窗. refresh=100 表示在iteration方块中,将会以100为单位,显示正在update

的进度,refresh值愈小,将愈加重其显示的量,则update速度会变慢.

若thin方块中之数值改为5,表示每隔5笔收一笔资料,共收3000笔,以整

个Markov chain来看,WinBugs会保留的样本是第5, 10, 15,…, 15000笔资料

6. 显示simulated values (posterior samples)

Step 1 在功能表列中点选:Inference → Samples,开启Sample Monitor Tool 视窗

Step 2 Sample Monitor Tool视窗内各个选项的执行程序与作用:

(1) 由於之前曾在此视窗中monitor各个参数,因而现在若欲同时显现所有

monitor 参数的结果,则可在node 方块中键入'*',以代表全体参数

若仅需部分参数的posterior samples及其统计推论结果,则在node方块中输

入该参数名即可.

(2) Burn in:为降低起始值的影响,选取递回後较稳定的资料,因此在分析时

常常需要Burn in 前面较不稳定的资料。

看下面 对string 的理解:

起因:

String a="Hello World!"

String b="Hello World!"

a==b? a和b是否相等 ? 为什么?

String a=new String("Hello World!")

String b="Hello World!"

a==b? a和b是否相等 ? 为什么?

解释:

1. 首先String不属于8种基本数据类型,String是一个对象

因为对象的默认值是null,所以String的默认值也是null;但它又是一种特殊的对象,有其它对象没有的一些特性。

2. new String()和new String(“”)都是申明一个新的空字符串,是空串不是null;

3. String str="kvill"和String str=new String (“kvill”)的区别:

在这里,我们不谈堆,也不谈栈,只先简单引入常量池这个简单的概念。

常量池(constant pool)指的是在编译期被确定,并被保存在已编译的.class文件中的

一些数据。它包括了关于类、方法、接口等中的常量,也包括字符串常量。

看例1:

String s0="kvill"

String s1="kvill"

String s2="kv" + "ill"

System.out.println( s0==s1 )

System.out.println( s0==s2 )

结果为:

true

true

首先,我们要知道Java会确保一个字符串常量只有一个拷贝。

因为例子中的s0和s1中的”kvill”都是字符串常量,它们在编译期就被确定了,所以

s0==s1为true;而”kv”和”ill”也都是字符串常量,当一个字符串由多个字符串常量连

接而成时,它自己肯定也是字符串常量,所以s2也同样在编译期就被解析为一个字符串常量,所以s2也是常量池中”kvill”的一个引用。所以我们得出s0==s1==s2

用new String() 创建的字符串不是常量,不能在编译期就确定,所以new String()

创建的字符串不放入常量池中,它们有自己的地址空间。

看例2:

String s0="kvill"

String s1=new String("kvill")

String s2="kv"+ new String("ill")

System.out.println( s0==s1 )

System.out.println( s0==s2 )

System.out.println( s1==s2 )

结果为:

false

false

false

例2中s0还是常量池中”kvill”的应用,s1因为无法在编译期确定,所以是运行时创

建的新对象”kvill”的引用,s2因为有后半部分new String(“ill”)所以也无法在编译

期确定,所以也是一个新创建对象”kvill”的应用明白了这些也就知道为何得出此结果了。

4. String.intern():

再补充介绍一点:存在于.class文件中的常量池,在运行期被JVM装载,并且可以扩充。String的intern()方法就是扩充常量池的一个方法;当一个String实例str调用intern()方法时,Java查找常量池中是否有相同Unicode的字符串常量,如果有,则返回其的引用,如果没有,则在常量池中增加一个Unicode等于str的字符串并返回它的引用;

最后我再破除一个错误的理解:

有人说,“使用String.intern()方法则可以将一个String类的保存到一个全局Strin

g表中,如果具有相同值的Unicode字符串已经在这个表中,那么该方法返回表中已有字符串的地址,如果在表中没有相同值的字符串,则将自己的地址注册到表中“如果我把他说的这个全局的String表理解为常量池的话,他的最后一句话,“如果在表中没有相同值的字符串,则将自己的地址注册到表中”是错的:

看例4:

String s1=new String("kvill")

String s2=s1.intern()

System.out.println( s1==s1.intern() )

System.out.println( s1+" "+s2 )

System.out.println( s2==s1.intern() )

结果:

false

kvill kvill

true

在这个类中我们没有声名一个"kvill"常量,所以s1.intern()同new String("kvill")是不同的,当我们调用s1.intern()后就在常量池中新添加了一个"kvill"常量,原来的不在常量池中的"kvill"仍然存在,也就不是“将自己的地址注册到常量池中”了。

s1==s1.intern()为false说明原来的“kvill”仍然存在;

s2现在为常量池中“kvill”的地址,所以有s2==s1.intern()为true。

5. 关于equals()和==:

这个对于String简单来说就是比较两字符串的Unicode序列是否相当,如果相等返回true而==是比较两字符串的地址是否相同,也就是是否是同一个字符串的引用。

6. 关于String是不可变的

这一说又要说很多,大家只要知道String的实例一旦生成就不会再改变了,比如说:

String str=”kv”+”ill”+” “+”ans”

就是有4个字符串常量,首先”kv”和”ill”生成了”kvill”存在内存中,然后”kvill”又和” “ 生成 ”kvill “存在内存中,最后又和生成了”kvill ans”并把这个字符串的地址赋给了str,就是因为String的“不可变”产生了很多临时变量,这也就是为什么建议用StringBuffer的原因了,因为StringBuffer是可改变的。

String到底变了没有?

没有。因为String被设计成不可变(immutable)类,所以它的所有对象都是不可变对象。请看下列代码:

String s = "Hello"

s = s + " world!"

s 所指向的对象是否改变了呢?

我们来看看发生了什么事情。在这段代码中,s原先指向一个String对象,内容是 "Hello",然后我们对s进行了+ *** 作,那么s所指向的那个对象是否发生了改变呢?答案是没有。这时,s不指向原来那个对象了,而指向了另一个 String对象,内容为"Hello world!",原来那个对象还存在于内存之中,只是s这个引用变量不再指向它了。

通过上面的说明,我们很容易导出另一个结论,如果经常对字符串进行各种各样的修改,或者说,不可预见的修改,那么使用String来代表字符串的话会引起很大的内存开销。因为String对象建立之后不能再改变,所以对于每一个不同的字符串,都需要一个String对象来表示。这时,应该考虑使用 StringBuffer 类,它允许修改,而不是每个不同的字符串都要生成一个新的对象。并且,这两种类的对象转换十分容易。

同时,我们还可以知道,如果要使用内容相同的字符串,不必每次都new一个String。例如我们要在构造器中对一个名叫s的String引用变量进行初始化,把它设置为初始值,应当这样做:

public class Demo {

private String s

...

public Demo {

s = "Initial value"

}

...

}

而非

s = new String("Initial value")

后者每次都会调用构造器,生成新对象,性能低下且内存开销大,并且没有意义,因为String对象不可改变,所以对于内容相同的字符串,只要一个 String对象来表示就可以了。也就说,多次调用上面的构造器创建多个对象,他们的String类型属性s都指向同一个对象。

上面的结论还基于这样一个事实:对于字符串常量,如果内容相同,Java认为它们代表同一个String对象。而用关键字new调用构造器,总是会创建一个新的对象,无论内容是否相同。

至于为什么要把String类设计成不可变类,是它的用途决定的。其实不只String,很多Java标准类库中的类都是不可变的。在开发一个系统的时候,我们有时候也需要设计不可变类,来传递一组相关的值,这也是面向对象思想的体现。不可变类有一些优点,比如因为它的对象是只读的,所以多线程并发访问也不会有任何问题。当然也有一些缺点,比如每个不同的状态都要一个对象来代表,可能会造成性能上的问题。所以Java标准类库还提供了一个可变版本,即 StringBuffer。

7.注意

看下面例子:

public class StringTest

{

public static void main(String[] args)

{

String str1 = "hello"

String str2 = "hel"

str2 = str2 + "lo"

System.out.println("str1 == str2 :" + (str1 == str2))

}

}

实际会打出false

为什么呢,关键就在于str2=str2+"lo"是不能能编译期就确定的

str1是在内存池没错,但str2不是~

用反编译工具反编译一下class文件就会发现

str2 =str2+"lo"

实际上是:

str2 = (new StringBuilder()).append(str2).append("lo").toString()

显然,str2是new出来的(不信去看看StringBuilder的源代码)

看例3就清楚了。

例3:

String s0= "kvill"

String s1=new String("kvill")

String s2=new String("kvill")

System.out.println( s0==s1 )

System.out.println( “**********” )

s1.intern()

s2=s2.intern()//把常量池中"kvill"的引用赋给s2

System.out.println( s0==s1)

System.out.println( s0==s1.intern() )

System.out.println( s0==s2 )

结果为:

false

**********

false //虽然执行了s1.intern(),但它的返回值没有赋给s1

true //说明s1.intern()返回的是常量池中”kvill”的引用

true

java中“@”大多代表注解的意思。那么@param是用来在DAO层中声明参数的注解方式。

例如:

List<News>selectByUserIdAndOffset(@Param("userId") int userId, @Param("offset") int offset, @Param("limit") int limit)

@ param标签可以归档方法或构造器的某个单一参数,或者归档类、接口以及泛型方法的类型参数。在使用@ param标签时,我们应该针对方法的每一个参数都使用一个该标签。每个段落的第一个词会被当作参数名,而余下的部分则会被当作是对它的描述。

扩展资料:

注解的语法比较简单,除了@符号的使用之外,它基本与Java固有语法一致。Java SE5内置了三种标准注解:

@Override,表示当前的方法定义将覆盖超类中的方法。

@Deprecated,使用了注解为它的元素编译器将发出警告,因为注解@Deprecated是不赞成使用的代码,被弃用的代码。

@SuppressWarnings,关闭不当编译器警告信息。

参考资料:

Java中@param注解的作用-脚本之家


欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/tougao/7882303.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-04-11
下一篇 2023-04-11

发表评论

登录后才能评论

评论列表(0条)

保存