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注解的作用-脚本之家
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)