楼主: 夏目贵志
6481 6

[学习心得] 原创:如何让Stata更快的进行maximum likelihood计算 [推广有奖]

贵宾

已卖:483份资源

学科带头人

96%

还不是VIP/贵宾

-

威望
1
论坛币
238675 个
通用积分
17659.3894
学术水平
851 点
热心指数
971 点
信用等级
711 点
经验
759469 点
帖子
4028
精华
1
在线时间
793 小时
注册时间
2012-7-15
最后登录
2017-9-16

楼主
夏目贵志 发表于 2013-5-7 21:44:27 |AI写论文

+2 论坛币
k人 参与回答

经管之家送您一份

应届毕业生专属福利!

求职就业群
赵安豆老师微信:zhaoandou666

经管之家联合CDA

送您一个全额奖学金名额~ !

感谢您参与论坛问题回答

经管之家送您两个论坛币!

+2 论坛币
这几天正在使用maximum likelihood方法估计discrete choice模型。很多情况下,计算likelihood的程序需要根据被解释变量y的取值来计算likelihood `lnf'。达成这个目的常见的方法是使用if条件语句。例如:
  1. program lfprobit  
  2.     version 10.1  
  3.     args lnf xb  
  4.     local y "$ML_y1"  
  5.     quietly replace `lnf' = ln(  normal(`xb')) if `y'==1  
  6.     quietly replace `lnf' = ln(1-normal(`xb')) if `y'==0
  7. end
复制代码
当数据量较大(例如,超过10万)时,这样计算likelihood耗费的时间太长,从而影响这个maximum likelihood估计的速度。这时,只要对算法稍加改进,就能大幅度提高运算速度!

这个改进其实很简单。原理就是用in语句代替if语句。大家一看下面的例子就会明白了。

剧透一下:试验结果表明,当数据包含20万观测值时,使用in条件比默认的使用if条件来计算likelihood可以使运算速度减少(相对于默认算法)40%至50%!
  1. // testing speed of updating likelihood function
  2. // =============================================

  3. foreach iter in 100 200 500 1000 {

  4. clear all

  5. // set up testing parameters
  6. set seed 130507
  7. set obs 200000

  8. // setting up dependent variable so it assumes values 1 to 3
  9. cap drop depvar
  10. gen depvar = runiform()
  11. qui su depvar, d
  12. replace depvar = 1 if depvar<r(p25)
  13. replace depvar = 2 if depvar!=1&depvar<r(p75)
  14. replace depvar = 3 if depvar!=1&depvar!=2
  15. // confirm that depvar is set correctly
  16. noi su depvar
  17. noi levelsof depvar

  18. // setting up xb variable and placeholder for likelihood
  19. cap drop lnf xb
  20. gen lnf = .
  21. gen xb = runiform()

  22. // initialize timer
  23. timer clear 1
  24. timer clear 2
  25. timer clear 3
  26. timer clear 4

  27. // NOTE: the data is NOT sorted by depvar.

  28. // first method of updating the likelihood, the default, as benchmark
  29. timer on 1
  30. forvalues i = 1/`iter' {
  31.     replace lnf=ln(normal(0-xb)) if depvar==1
  32.     replace lnf=ln(normal(2-xb)-normal(0-xb)) if depvar==2
  33.     replace lnf=ln(1-normal(2-xb)) if depvar==3
  34. }
  35. timer off 1

  36. // second method of updating the likelihood
  37. timer on 2
  38. forvalues i = 1/`iter' {
  39.     replace lnf=ln(normal(0-xb))*(depvar==1)+ln(normal(2-xb)-normal(0-xb))*(depvar==2)+ln(1-normal(2-xb))*(depvar==3)
  40. }
  41. timer off 2

  42. // now sort the data and see if speeds up the default method
  43. sort depvar
  44. timer on 3
  45. forvalues i = 1/`iter' {
  46.     replace lnf=ln(normal(0-xb)) if depvar==1
  47.     replace lnf=ln(normal(2-xb)-normal(0-xb)) if depvar==2
  48.     replace lnf=ln(1-normal(2-xb)) if depvar==3
  49. }
  50. timer off 3

  51. // finally, try the updating method using in conditions
  52. // as counting is part of the procedure, start timer before counting
  53. timer on 4
  54. // note that a forvalues loop can be easily constructed if number of
  55. // categories of the dependent variable is unknown
  56. sort depvar
  57. count if depvar==1
  58. local start1 = 1
  59. local end1 = r(N)
  60. count if depvar==2
  61. local start2 = `end1'+1
  62. local end2 = `start2'+r(N)-1
  63. local start3 = `end2'+1
  64. // finished counting, start updating using in conditions
  65. // note that without loss of generality it is assumed that the entire data set is used.
  66. // unused portion of the data set can be dropped after preserve then restore
  67. // after the program finished
  68. forvalues i = 1/`iter' {
  69.     replace lnf=ln(normal(0-xb)) in `start1'/`end1'
  70.     replace lnf=ln(normal(2-xb)-normal(0-xb)) in `start2'/`end2'
  71.     replace lnf=ln(1-normal(2-xb)) in `start3'/l
  72. }
  73. timer off 4

  74. // list results
  75. noi di "Benchmark: using if conditions before sorting"
  76. noi timer list 1
  77. noi di "Method 2"
  78. noi timer list 2
  79. noi di "Using default method after sorting"
  80. noi timer list 3
  81. noi di "Proposed alternative using in conditions"
  82. noi timer list 4

  83. // clean up
  84. drop depvar lnf xb
  85. timer clear 1
  86. timer clear 2
  87. timer clear 3
  88. timer clear 4

  89. } // end foreach
复制代码
执行的结果是:
  1. Number of iterations:  100
  2. Benchmark: using if conditions before sorting
  3.    1:      2.36 /        1 =       2.3560
  4. Method 2
  5.    2:      4.87 /        1 =       4.8670
  6. Using default method after sorting
  7.    3:      4.35 /        1 =       4.3530
  8. Proposed alternative using in conditions
  9.    4:      1.37 /        1 =       1.3730
复制代码
  1. Number of iterations:  200
  2. Benchmark: using if conditions before sorting
  3.    1:      4.88 /        1 =       4.8830
  4. Method 2
  5.    2:      9.59 /        1 =       9.5940
  6. Using default method after sorting
  7.    3:      8.74 /        1 =       8.7360
  8. Proposed alternative using in conditions
  9.    4:      2.65 /        1 =       2.6520
复制代码
  1. Number of iterations:  500
  2. Benchmark: using if conditions before sorting
  3.    1:     11.72 /        1 =      11.7160
  4. Method 2
  5.    2:     23.81 /        1 =      23.8050
  6. Using default method after sorting
  7.    3:     21.67 /        1 =      21.6680
  8. Proposed alternative using in conditions
  9.    4:      6.63 /        1 =       6.6300
复制代码
  1. Number of iterations: 1000
  2. Benchmark: using if conditions before sorting
  3.    1:     23.35 /        1 =      23.3540
  4. Method 2
  5.    2:     48.55 /        1 =      48.5470
  6. Using default method after sorting
  7.    3:     43.29 /        1 =      43.2900
  8. Proposed alternative using in conditions
  9.    4:     13.26 /        1 =      13.2600
复制代码
二维码

扫码加我 拉你入群

请注明:姓名-公司-职位

以便审核进群资格,未注明则拒绝

关键词:Likelihood Maximum Stata tata like 如何 计算 version replace choice

已有 1 人评分论坛币 学术水平 收起 理由
dxystata + 100 + 1 精彩帖子

总评分: 论坛币 + 100  学术水平 + 1   查看全部评分

本帖被以下文库推荐

沙发
kerrydu 发表于 2014-4-19 17:04:36
为什么sort之后,变慢了呢

藤椅
夏目贵志 发表于 2014-4-22 21:09:52
kerrydu 发表于 2014-4-19 17:04
为什么sort之后,变慢了呢
把你的程序和运行结果贴出来。你在你机器上运行我贴出来的那个程序了吗?结果如何?

板凳
夏目贵志 发表于 2014-4-22 21:34:34
我在我的新电脑上重新运行了一下上面的程序,效果还是很明显的。
  1. . run "C:\SYStemp\STD03000000.tmp"

  2.     Variable |       Obs        Mean    Std. Dev.       Min        Max
  3. -------------+--------------------------------------------------------
  4.       depvar |    200000           2    .7071085          1          3
  5. 1 2 3
  6. Benchmark: using if conditions before sorting
  7.    1:      1.43 /        1 =       1.4260
  8. Method 2
  9.    2:      2.35 /        1 =       2.3450
  10. Using default method after sorting
  11.    3:      2.61 /        1 =       2.6120
  12. Proposed alternative using in conditions
  13.    4:      0.83 /        1 =       0.8300

  14.     Variable |       Obs        Mean    Std. Dev.       Min        Max
  15. -------------+--------------------------------------------------------
  16.       depvar |    200000           2    .7071085          1          3
  17. 1 2 3
  18. Benchmark: using if conditions before sorting
  19.    1:      2.68 /        1 =       2.6770
  20. Method 2
  21.    2:      4.66 /        1 =       4.6620
  22. Using default method after sorting
  23.    3:      5.27 /        1 =       5.2690
  24. Proposed alternative using in conditions
  25.    4:      1.80 /        1 =       1.8000

  26.     Variable |       Obs        Mean    Std. Dev.       Min        Max
  27. -------------+--------------------------------------------------------
  28.       depvar |    200000           2    .7071085          1          3
  29. 1 2 3
  30. Benchmark: using if conditions before sorting
  31.    1:      6.89 /        1 =       6.8920
  32. Method 2
  33.    2:     11.87 /        1 =      11.8710
  34. Using default method after sorting
  35.    3:     12.93 /        1 =      12.9290
  36. Proposed alternative using in conditions
  37.    4:      5.02 /        1 =       5.0190

  38.     Variable |       Obs        Mean    Std. Dev.       Min        Max
  39. -------------+--------------------------------------------------------
  40.       depvar |    200000           2    .7071085          1          3
  41. 1 2 3
  42. Benchmark: using if conditions before sorting
  43.    1:     14.89 /        1 =      14.8870
  44. Method 2
  45.    2:     27.89 /        1 =      27.8860
  46. Using default method after sorting
  47.    3:     28.78 /        1 =      28.7780
  48. Proposed alternative using in conditions
  49.    4:     10.99 /        1 =      10.9900
  50. r; t=141.62 9:12:49
复制代码

报纸
kerrydu 发表于 2014-4-22 22:02:29
夏目贵志 发表于 2014-4-22 21:34
我在我的新电脑上重新运行了一下上面的程序,效果还是很明显的。
我也试过了,确实是这样。但实质上第3与第1没区别,不知道为什么加了个sort反而慢了这么多,难以理解
已有 1 人评分学术水平 收起 理由
夏目贵志 + 1 精彩帖子

总评分: 学术水平 + 1   查看全部评分

地板
夏目贵志 发表于 2014-4-22 23:14:12
kerrydu 发表于 2014-4-22 22:02
我也试过了,确实是这样。但实质上第3与第1没区别,不知道为什么加了个sort反而慢了这么多,难以理解
不好意思,我一开始没看明白你的问题。现在明白了。

7
夏目贵志 发表于 2014-4-22 23:33:55
kerrydu 发表于 2014-4-22 22:02
我也试过了,确实是这样。但实质上第3与第1没区别,不知道为什么加了个sort反而慢了这么多,难以理解
我又反复做了一下这个实验,尝试了很多别的方法(比如反向sort和随机sort等等),也尝试了一些别的命令,比如count。似乎只有replace才会存在这个现象。

我这两个月实在事情太多。你要是有兴趣的话可以去statalist发个邮件问问。说不定这个是stata的bug呢。

我用的stata12。别的版本我没试过。

您需要登录后才可以回帖 登录 | 我要注册

本版微信群
加好友,备注jltj
拉您入交流群
GMT+8, 2025-12-20 23:10