• 标准正态累积分布函数


    [公式]为标准正态累积分布函数:

    [公式]

    最大绝对误差0.0017。

    高斯分布的解析式是 [公式] 形式,它不可积、没有原函数。但是有时候有需要知道高斯分布任意一段区间的面积,这时就需要用到高斯分布的可积分拟合函数。高斯分布的可积分拟合函数有很多,其中一种形式如下式所示。

    [公式]

    我们只需要找到满足上式f(x),那么我们就得到了高斯分布的可积分拟合函数。因为高斯分布具有对称性,所以只考虑x负半轴上的正态分布。

    不妨设 [公式] 是多项式函数,求解的参数包括:多项式中每一项的系数。

    [公式]

    求解非线性方程组,瞬间可得很多个可积分的高斯分布。

    以下程序尝试了最小二乘法和tensorflow调参两种方法求解非线性方程组。

      1 import matplotlib.pyplot as plt
      2 import numpy as np
      3 import tensorflow as tf
      4 from scipy import optimize
      5 
      6 """
      7 正态分布的拟合是一个很难调节的神经网络
      8 
      9 并非每次运行都能找到合适的解
     10 """
     11 
     12 
     13 def gauss(xs, mu=0, sigma=1):
     14     return 1 / (sigma * (2 * np.pi) ** 0.5) * np.exp(-(xs - mu) ** 2 / (2 * sigma ** 2))
     15 
     16 
     17 def my_fun(v):
     18     x = np.linspace(-3.5, 0.1, 1000)
     19     vv = np.empty(len(v) - 1)
     20     for i in range(len(vv)):
     21         vv[i] = v[i + 1] * (i + 1)
     22     y = (
     23         (x.reshape(-1, 1) ** np.arange(len(vv)))
     24         @ vv
     25         * np.exp((x.reshape(-1, 1) ** np.arange(len(v))) @ v)
     26     )
     27     yy = gauss(x)
     28     l = y - yy
     29     print(np.linalg.norm(l))
     30     return l
     31 
     32 
     33 def draw(v):
     34     x = np.linspace(-3.5, 3.5, 100)
     35     vv = np.empty(len(v) - 1)
     36     for i in range(len(vv)):
     37         vv[i] = v[i + 1] * (i + 1)
     38     y = (
     39         (x.reshape(-1, 1) ** np.arange(len(vv)))
     40         @ vv
     41         * np.exp((x.reshape(-1, 1) ** np.arange(len(v))) @ v)
     42     )
     43     yy = gauss(x)
     44     plt.plot(x, y, label="mine")
     45     plt.plot(x, yy, label="real")
     46     plt.legend()
     47     plt.ylim(0, 1)
     48     plt.xlim(x.min(), x.max())
     49     plt.show()
     50 
     51 
     52 def print_latex(v):
     53     def pow(y):
     54         if y == 0:
     55             return ""
     56         if y == 1:
     57             return "x"
     58         return f"x^{y}"
     59 
     60     s = r"""\frac{1}{\sqrt{2\pi}}e^{-\frac{1}{2}x^2}="""
     61     pre = f"{v[1]:.3f}"
     62     for i in range(1, len(v) - 1):
     63         if v[i + 1] >= 0 and i > 0:
     64             pre += "+"
     65         pre += f"{v[i+1]:.3f} \\times {i+1}{pow(i)}"
     66     post = ""
     67     for i in range(len(v)):
     68         if v[i] >= 0 and i > 0:
     69             post += "+"
     70         post += f"{v[i]:.3f}{pow(i)}"
     71     ss = f"({pre}) \\times e^{{{post}}}"
     72     s = s + ss + r"\\"
     73     print(s)
     74 
     75 
     76 def get_params_by_tf(n):
     77     x = np.linspace(-3.5, 0.1, 10000)
     78     y = gauss(x)
     79     x_place = tf.placeholder(dtype=tf.float32, shape=(None,))
     80     y_place = tf.placeholder(dtype=tf.float32, shape=(None,))
     81     v = tf.Variable(tf.random.uniform((n,), minval=0, maxval=0.1))
     82     learn_rate = tf.Variable(0.01, trainable=False)
     83     pre = 0
     84     for i in range(n - 1):
     85         pre += x_place ** i * v[i + 1] * (i + 1)
     86     post = 0
     87     for i in range(n):
     88         post += x_place ** i * v[i]
     89     y_output = pre * tf.exp(post)
     90     # lo = tf.reduce_max(tf.abs(y_output - y_place))
     91     # lo = tf.reduce_sum((y_output - y_place) ** 2)
     92     # lo = tf.reduce_sum(tf.abs(y_output - y_place))
     93     lo = tf.linalg.norm(y_output - y_place)
     94     train_op = tf.train.AdamOptimizer(learn_rate).minimize(lo)
     95     with tf.Session() as sess:
     96         sess.run(tf.global_variables_initializer())
     97         last = None
     98         for epoch in range(10000):
     99             _, l = sess.run((train_op, lo), feed_dict={x_place: x, y_place: y})
    100             if epoch % 1000 == 0:
    101                 rate = sess.run(learn_rate) * 0.99
    102                 rate = max(rate, 0.0001)
    103                 sess.run(tf.assign(learn_rate, rate))
    104                 print(epoch, l)
    105                 if last is None:
    106                     last = l
    107                 else:
    108                     if abs(last - l) < 0.0001:
    109                         print("last loss", l)
    110                         break
    111                     last = l
    112         res = sess.run(v)
    113         return res
    114 
    115 
    116 def get_param_by_fsolve(n):
    117     v = optimize.leastsq(my_fun, np.random.random(n) - 0.5)
    118     print("loss", v[1])
    119     return v[0]
    120 
    121 
    122 def wrap_get_param(n):
    123     l = 1
    124     res = None
    125     while l > 0.1:
    126         res, l = get_params_by_tf(n)
    127     print("last loss", l)
    128     return res
    129 
    130 
    131 v = get_param_by_fsolve(5)
    132 print(v)
    133 print_latex(v)
    134 draw(v)

    效果如下:

     
  • 相关阅读:
    算法与数据结构(十五) 归并排序(Swift 3.0版)
    算法与数据结构(十四) 堆排序 (Swift 3.0版)
    算法与数据结构(十三) 冒泡排序、插入排序、希尔排序、选择排序(Swift3.0版)
    算法与数据结构(十二) 散列(哈希)表的创建与查找(Swift版)
    算法与数据结构(十一) 平衡二叉树(AVL树)(Swift版)
    算法与数据结构(十) 二叉排序树的查找、插入与删除(Swift版)
    算法与数据结构(九) 查找表的顺序查找、折半查找、插值查找以及Fibonacci查找(Swift版)
    算法与数据结构(八) AOV网的关键路径(Swift版)
    算法与数据结构(七) AOV网的拓扑排序(Swift版)
    算法与数据结构(六) 迪杰斯特拉算法的最短路径(Swift版)
  • 原文地址:https://www.cnblogs.com/guochaoxxl/p/16256929.html
Copyright © 2020-2023  润新知