Engee 文档
Notebook

随机变量在不同坐标系中的分布

本示例将介绍以下主题:

-Julia中的随机数和数组生成
-使用概率分布
-根据问题陈述选择随机变量的正确分布的重要性。

默认随机数生成

功能 rand()

为了生成随机数,您可以在不连接库的情况下使用该函数。 rand() . 它将返回范围内的随机实数 [0,1)

In [ ]:
Pkg.add(["Distributions"])
In [ ]:
rand()
Out[0]:
0.8968475595278809

如果需要创建矩阵 具有元素的一定尺寸 ,那么我们将使用 rand(i,j,k)

In [ ]:
rand(2,4,3)
Out[0]:
2×4×3 Array{Float64, 3}:
[:, :, 1] =
 0.105281  0.553249  0.571817  0.068993
 0.463789  0.510086  0.468581  0.599769

[:, :, 2] =
 0.845341  0.959642  0.488022  0.959579
 0.409156  0.49006   0.548231  0.899735

[:, :, 3] =
 0.957553  0.136052  0.885431  0.284849
 0.826566  0.92279   0.659209  0.384685

如果在 rand() 转移元组:

rand((2,4,3)),

那个 (2,4,3) 将有一组元素从中选择随机元素

In [ ]:
rand((2,4,3))
Out[0]:
4
In [ ]:
rand(('a',3,"string",1+1im),2,3)
Out[0]:
2×3 Matrix{Any}:
   "string"  'a'    "string"
 1+1im       'a'  1+1im

您还可以将字典作为一组元素传递。:

In [ ]:
rand(Dict("pi" => 3.14, "e" => 2.71), 3)
Out[0]:
3-element Vector{Pair{String, Float64}}:
 "e" => 2.71
 "e" => 2.71
 "e" => 2.71

分布的可视化分析

为了直观地评估生成数字的规律,我们将使用图书馆 Plots. 要做到这一点,请使用 using Plots 之后我们将使用该函数 histogram. 通过写作 gr() -禁用与图表交互的可能性。

In [ ]:
using Plots             # подключаем библиотеку
gr()                    # отключаем интерактивное взаимодействие с графиком, т.к. точек много
histogram(rand(50000))  # строим гистограму 
title!("rand(50000)")   # подпись
Out[0]:

从直方图中可以看出,使用rand()生成的随机数的分布是均匀。 即功能 rand() 生成具有标准连续均匀分布(SNR)的值

正态分布

此外,在不连接其他库的情况下,Julia可以生成具有正态分布的随机数。

Randn()函数生成具有数学期望的数字的正态分布 0 和标准偏差 1. (即值的范围将是 )

In [ ]:
histogram(randn(50000),bims=0.005) # bims - ширина стобца, в который попадает точка
title!("randn(50000)")
Out[0]:

选择随机变量的正确分布的重要性

让我们考虑这样的任务:

在半径圆内创建一组点 R=1 并以 (0,0),其直角坐标沿横坐标和纵坐标轴均匀分布。 为了这个

  1. 创建一组落入正方形的点,对角线穿过顶点 (-1,1), (1,-1)
  2. 选择落在单位圆内的点。

第1步。

要解决这一步,有必要记住,我们希望得到均匀分布的值。 X 范围内的 [-1,1]. 但是 rand() -SNRR(即 [0,1)).

SNRR[拥有](https://ru.wikipedia.org/wiki/Contigue_uniform_allocation)由缩放属性:
如果随机变量 然后

在我们的例子中

In [ ]:
POINTS_NUMBER = 3000
big_square_points = -1 .+ 2. .* rand(POINTS_NUMBER, 2)  # воспользовались свойством СНРР
Out[0]:
3000×2 Matrix{Float64}:
  0.0529451    -0.378398
 -0.926168     -0.595867
 -0.506066      0.586659
 -0.349772     -0.501738
 -0.199344     -0.742828
  0.869969      0.759997
  0.0879778    -0.111934
 -0.601932     -0.955655
  0.678965      0.0709128
 -0.873571     -0.671576
  0.161069      0.667479
  0.32568       0.848502
  0.14866      -0.0551039
  ⋮            
 -0.403644     -0.839549
 -0.103682     -0.11301
 -0.958197     -0.63964
  0.0131706     0.507728
  0.0394808     0.353285
 -0.948482     -0.794558
 -0.870387     -0.195976
  0.980847      0.716624
 -0.987589      0.0785435
  0.897117     -0.967298
  0.000805525  -0.625087
 -0.112197     -0.540335

为了避免在绘制图形时每次都使用相同的关键字,您可以添加 PlotThemes 并写必要的话"默认"。

In [ ]:
Pkg.add("PlotThemes")
theme(:default, aspect_ratio=1, label = false, markersize=1)
scatter(big_square_points[:,1],big_square_points[:,2])  
   Resolving package versions...
  No Changes to `~/.project/Project.toml`
  No Changes to `~/.project/Manifest.toml`
Out[0]:

第二步

我们将遍历正方形的所有点,并将落在单位圆内的坐标添加到数组中。

In [ ]:
circle_points_x = Float64[]
circle_points_y = Float64[]
R = 1
for (x, y) in eachrow(big_square_points) # (в каждой строке big_square_points 2 элемента: x и y)
    if x^2 + y^2 < R^2
        push!(circle_points_x, x)
        push!(circle_points_y, y)
    end
end
scatter(circle_points_x,circle_points_y)
Out[0]:

为了解决我们的问题,更自然的方法是使用极坐标而不是笛卡尔坐标。

使用极坐标

然后这个任务将减少到一个,而不是两个步骤。:

步骤1
选择

In [ ]:
ρ = rand(POINTS_NUMBER)
α = 2π * rand(POINTS_NUMBER)
polar_original = scatter(ρ .* cos.(α), ρ .* sin.(α), aspect_ratio=1,markersize=1)  # перешли обратно в декартовы
Out[0]:

您也可以立即查看我们的结果,而无需切换到笛卡尔坐标。 要做到这一点,首先禁用 aspect_ratio=1 并指定 proj=:polar -极地映射。

In [ ]:
theme(:default)
scatter(α, ρ , proj=:polar, markersize=1)
Out[0]:

我们可以看到,原点附近的点的密度高于圆附近。

为了清楚起见,我们将从圆圈中切出一个刻有方块的正方形。

为此,我们将使用该函数 zip():

In [ ]:
for i in zip(1:5,'a':'e',["🟥","🟩","🟦"])
    println(i)
end
# 4,5 и 'd','e' не напечатаются, так как коллекция цветов закончилась на 3 шаге
(1, 'a', "🟥")
(2, 'b', "🟩")
(3, 'c', "🟦")

点密度可视化

In [ ]:
small_square_points_x = Float64[]
small_square_points_y = Float64[]

for (x, y) in zip(circle_points_x, circle_points_y)
    if abs(x)  2 / 2 && abs(y)  2 / 2
        push!(small_square_points_x, x)
        push!(small_square_points_y, y)
    end
end
In [ ]:
small_square_points_ρ = Float64[]
small_square_points_α = Float64[]

for (x, y) in zip(ρ .* cos.(α), ρ .* sin.(α))
    if abs(x)  2 / 2 && abs(y)  2 / 2
        push!(small_square_points_ρ, x)
        push!(small_square_points_α, y)
    end
end

要一次在同一画布上显示多个图形,您必须使用 layout 并指定其位置的结构(在我们的例子中,网格 . 使用 histogram2d 我们将能够看到在哪个区域有高密度的点。

In [ ]:
p1 = scatter(   small_square_points_x, small_square_points_y,
                markersize=1, legend = false, aspect_ratio=1)
p2 = scatter(   small_square_points_ρ, small_square_points_α,
                markersize=1, legend = false, aspect_ratio=1)
p3 = histogram2d(small_square_points_x,small_square_points_y,
                 title="плотность в декартовых координатах", aspect_ratio=1)
p4 = histogram2d(small_square_points_ρ,small_square_points_α,
                 title="плотность в полярных координатах",aspect_ratio=1)

plot(p1,p2,p3,p4,layout=(2,2),size=(950,950))
Out[0]:

功能 repeat()

考虑功能 repeat()

In [ ]:
repeat([1:3;],2)
Out[0]:
6-element Vector{Int64}:
 1
 2
 3
 1
 2
 3
In [ ]:
repeat([1:3;],1,2)
Out[0]:
3×2 Matrix{Int64}:
 1  1
 2  2
 3  3
In [ ]:
repeat([1:3;],2,3)
Out[0]:
6×3 Matrix{Int64}:
 1  1  1
 2  2  2
 3  3  3
 1  1  1
 2  2  2
 3  3  3
In [ ]:
repeat([1:3;],inner=2)
Out[0]:
6-element Vector{Int64}:
 1
 1
 2
 2
 3
 3

极坐标和笛卡尔坐标的比较

为了理解为什么应用极坐标和随机均匀分布 如果他们以这种方式工作,而不是,也许,以预期的方式,考虑下面的图片。
让我们采取的不是随机的,而是一个固定的均匀分布。:

In [ ]:
lngt = 12
a = repeat(range(0, stop=2pi,length=lngt),1,lngt)
r = repeat(range(0, stop=1, length=lngt),1,lngt)'
scatter(r .* cos.(a), r .* sin.(a),aspect_ratio=1, markersize=3)
Out[0]:
In [ ]:
x = repeat(range(0, stop=1, length=lngt),1,lngt)'
y = repeat(range(0, stop=1,length=lngt),lngt)
scatter(x, y,aspect_ratio=1)
Out[0]:

如您所见,点在笛卡尔坐标中的分布密度是恒定的,而在极坐标中,密度在原点附近。

为了解决这个问题,我们需要使用一个分布,该分布更有可能使一个点更接近半径矢量的末端而不是开始。 让我们假设这样的分布应该是线性的(越接近末端,越有可能)。 它被称为三角形。

三角形分布

使用[三角形](https://en.wikipedia.org/wiki/Triangular_distribution )分发,连接库 Distributions. 这个库有一大组不同的状态(特别是一维状态)。 您可以在[文档]中熟悉此集(https://engee.com/helpcenter/stable/ru/julia/Distributions/univariate.html )。

In [ ]:
using Pkg   
Pkg.add("Distributions")
using Distributions
   Resolving package versions...
  No Changes to `~/.project/Project.toml`
  No Changes to `~/.project/Manifest.toml`

现在让我们创建一组具有三角形分布的点。 要做到这一点,作为函数的第一个参数 rand() 我们会传下去的 TriangularDist(a,b,c) 带参数 a=0,b=1,c=1.
Triangular_distribution_PMF.png

In [ ]:
histogram(rand(TriangularDist(0,1,1),POINTS_NUMBER))
Out[0]:

在确保三角形分布按预期工作后,让我们检查它的应用程序将解决我们的问题。:

In [ ]:
ρ_triang = rand(TriangularDist(0,1,1), POINTS_NUMBER)
α_triang = rand(Uniform(0,2π), POINTS_NUMBER)    # Uniform(0,2π) - равномерное распределение от 0 до 2π
polar_triang = scatter(ρ_triang .* cos.(α_triang), ρ_triang .* sin.(α_triang),aspect_ratio=1, markersize=1)
plot(polar_original, polar_triang,layout=(1,2))
Out[0]:

作为一个有趣的事实,我们将向您展示如何在没有 Distributions 只添加两个字符就可以解决这个问题。 .√ :

In [ ]:
ρ_sqrt = .√rand(POINTS_NUMBER)
α_sqrt = 2π * rand(POINTS_NUMBER)
scatter(α_sqrt, ρ_sqrt, proj=:polar, markersize=1)
Out[0]:

这是真的,因为:

使用均匀分布发生器,可以得到三角形分布发生器。:

结论

在这个例子中,Julia语言既有方便的内置函数,也有专门的包,允许您在与标准函数交互时使用特定于域的函数。

还考虑了生成数组的方法(repeat)并迭代它们(zipeachrow)