Sigmoid - x

背景

最近需要用 Sigmoid 处理数据,但是标准的 Sigmoid 在 x = 37 时就已经为 1 了,通常我们的数据量级是一定会大于 37 的,这时候就需要对 x 进行处理,调整 Sigmoid 中的 x 范围使得区分度高,并且尽量在 Sigmoid 的区间内均匀分布。

Sigmoid 的取值

首先,我们看一下 -50, 50 范围内的 Sigmoid,我这里只选取了 -20, 20 作为输出,精度和区分度基本已经符合我们的需求。

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
/**
* 计算 -50, 50 区间范围内的 sigmoid 值,选取区分度较高的区间
*/
for(Integer i = -50; i <= 50; i++) {
String s = String.format("%d %.20f",i , 1.0 / (Math.exp(i * -1.0) + 1.0));
System.out.println(s);
}
/** Sample Output
-20 0.00000000206115361819
-19 0.00000000560279640615
-18 0.00000001522997951276
-17 0.00000004139937547394
-16 0.00000011253516205510
-15 0.00000030590222692562
-14 0.00000083152802766413
-13 0.00000226032429790357
-12 0.00000614417460221472
-11 0.00001670142184809518
-10 0.00004539786870243440
-9 0.00012339457598623172
-8 0.00033535013046647810
-7 0.00091105119440064540
-6 0.00247262315663477430
-5 0.00669285092428485540
-4 0.01798620996209156000
-3 0.04742587317756678000
-2 0.11920292202211755000
-1 0.26894142136999510000
0 0.50000000000000000000
1 0.73105857863000490000
2 0.88079707797788230000
3 0.95257412682243340000
4 0.98201379003790850000
5 0.99330714907571530000
6 0.99752737684336530000
7 0.99908894880559940000
8 0.99966464986953360000
9 0.99987660542401370000
10 0.99995460213129760000
11 0.99998329857815200000
12 0.99999385582539780000
13 0.99999773967570200000
14 0.99999916847197220000
15 0.99999969409777300000
16 0.99999988746483790000
17 0.99999995860062440000
18 0.99999998477002050000
19 0.99999999439720360000
20 0.99999999793884630000
*/

Sigmoid 区间内 1 - 20 为底数的范围

通常情况下,(-6, 6) 的区间就基本满足我们的精度要求了,这时候可以看出来,大概以 10 为底的范围就已经很大了,我们根据目前数据所处的数量级选取合适的底数进行处理,可以选取 80%~90% 的数据极大极小值作为区间范围,然后再求得 Sigmoid 即可。

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
/**
* 这里选取了 1, 20 范围内, 区间为 0.1 的 sigmoid 范围为 -6, 6 的取值范围
*/
for(Double i = 1.0; i <= 20.0; i+=0.1) {
Double a = Math.pow(10, Math.log10(i)*(-6));
Double b = Math.pow(10, Math.log10(i)*(6));
String s = String.format("%.2f %.2f %.2f", i, a, b);
System.out.println(s);
}
/** Sample Output
3.00 0.00 729.00
3.10 0.00 887.50
3.20 0.00 1073.74
3.30 0.00 1291.47
3.40 0.00 1544.80
3.50 0.00 1838.27
3.60 0.00 2176.78
3.70 0.00 2565.73
3.80 0.00 3010.94
3.90 0.00 3518.74
4.00 0.00 4096.00
4.10 0.00 4750.10
4.20 0.00 5489.03
4.30 0.00 6321.36
4.40 0.00 7256.31
4.50 0.00 8303.77
4.60 0.00 9474.30
4.70 0.00 10779.22
4.80 0.00 12230.59
4.90 0.00 13841.29
5.00 0.00 15625.00
5.10 0.00 17596.29
5.20 0.00 19770.61
5.30 0.00 22164.36
5.40 0.00 24794.91
5.50 0.00 27680.64
5.60 0.00 30840.98
5.70 0.00 34296.45
5.80 0.00 38068.69
5.90 0.00 42180.53
6.00 0.00 46656.00
6.10 0.00 51520.37
6.20 0.00 56800.24
6.30 0.00 62523.50
6.40 0.00 68719.48
6.50 0.00 75418.89
6.60 0.00 82653.95
6.70 0.00 90458.38
6.80 0.00 98867.48
6.90 0.00 107918.16
7.00 0.00 117649.00
7.10 0.00 128100.28
7.20 0.00 139314.07
7.30 0.00 151334.23
7.40 0.00 164206.49
7.50 0.00 177978.52
7.60 0.00 192699.93
7.70 0.00 208422.38
7.80 0.00 225199.60
7.90 0.00 243087.46
8.00 0.00 262144.00
8.10 0.00 282429.54
8.20 0.00 304006.67
8.30 0.00 326940.37
8.40 0.00 351298.03
8.50 0.00 377149.52
8.60 0.00 404567.24
8.70 0.00 433626.20
8.80 0.00 464404.09
8.90 0.00 496981.29
9.00 0.00 531441.00
9.10 0.00 567869.25
9.20 0.00 606355.00
9.30 0.00 646990.18
9.40 0.00 689869.78
9.50 0.00 735091.89
9.60 0.00 782757.79
9.70 0.00 832972.00
9.80 0.00 885842.38
9.90 0.00 941480.15
10.00 0.00 1000000.00
*/

正确的操作方式

1
2
3
Math.pow(10, Math.log10(max) / exp);
// exp 是你根据精度选取的范围,比如上边的 -6, 6
// max 是你数据的最大值