Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Download
96129 views
1
# -*- coding: utf-8 -*-
2
3
"""Copyright 2015 Roger R Labbe Jr.
4
5
FilterPy library.
6
http://github.com/rlabbe/filterpy
7
8
Documentation at:
9
https://filterpy.readthedocs.org
10
11
Supporting book at:
12
https://github.com/rlabbe/Kalman-and-Bayesian-Filters-in-Python
13
14
This is licensed under an MIT license. See the readme.MD file
15
for more information.
16
"""
17
18
19
import numpy as np
20
from numpy.random import random
21
22
23
24
def residual_resample(weights):
25
""" Performs the residual resampling algorithm used by particle filters.
26
27
Based on observation that we don't need to use random numbers to select
28
most of the weights. Take int(N*w^i) samples of each particle i, and then
29
resample any remaining using a standard resampling algorithm [1]
30
31
32
**Parameters**
33
weights : list-like of float
34
list of weights as floats
35
36
**Returns**
37
38
indexes : ndarray of ints
39
array of indexes into the weights defining the resample. i.e. the
40
index of the zeroth resample is indexes[0], etc.
41
42
**References**
43
.. [1] J. S. Liu and R. Chen. Sequential Monte Carlo methods for dynamic
44
systems. Journal of the American Statistical Association,
45
93(443):1032–1044, 1998.
46
"""
47
48
N = len(weights)
49
indexes = np.zeros(N, 'i')
50
51
# take int(N*w) copies of each weight, which ensures particles with the
52
# same weight are drawn uniformly
53
num_copies = (np.floor(N*np.asarray(weights))).astype(int)
54
k = 0
55
for i in range(N):
56
for _ in range(num_copies[i]): # make n copies
57
indexes[k] = i
58
k += 1
59
60
# use multinormal resample on the residual to fill up the rest. This
61
# maximizes the variance of the samples
62
residual = weights - num_copies # get fractional part
63
residual /= sum(residual) # normalize
64
cumulative_sum = np.cumsum(residual)
65
cumulative_sum[-1] = 1. # avoid round-off errors: ensures sum is exactly one
66
indexes[k:N] = np.searchsorted(cumulative_sum, random(N-k))
67
68
return indexes
69
70
71
72
def stratified_resample(weights):
73
N = len(weights)
74
# make N subdivisions, and chose a random position within each one
75
positions = (random(N) + range(N)) / N
76
77
indexes = np.zeros(N, 'i')
78
cumulative_sum = np.cumsum(weights)
79
i, j = 0, 0
80
while i < N:
81
if positions[i] < cumulative_sum[j]:
82
indexes[i] = j
83
i += 1
84
else:
85
j += 1
86
return indexes
87
88
89
def systematic_resample(weights):
90
N = len(weights)
91
92
# make N subdivisions, and choose positions with a consistent random offset
93
positions = (random() + np.arange(N)) / N
94
95
indexes = np.zeros(N, 'i')
96
cumulative_sum = np.cumsum(weights)
97
i, j = 0, 0
98
while i < N:
99
if positions[i] < cumulative_sum[j]:
100
indexes[i] = j
101
i += 1
102
else:
103
j += 1
104
return indexes
105
106
107
108
def multinomial_resample(weights):
109
""" This is the naive form of roulette sampling where we compute the
110
cumulative sum of the weights and then use binary search to select the
111
resampled point based on a uniformly distributed random number. Run time
112
is O(n log n).
113
114
**Parameters**
115
weights : list-like of float
116
list of weights as floats
117
118
**Returns**
119
120
indexes : ndarray of ints
121
array of indexes into the weights defining the resample. i.e. the
122
index of the zeroth resample is indexes[0], etc.
123
"""
124
cumulative_sum = np.cumsum(weights)
125
cumulative_sum[-1] = 1. # avoid round-off errors: ensures sum is exactly one
126
return np.searchsorted(cumulative_sum, random(len(weights)))
127
128
129
if __name__ == '__main__':
130
w = np.array([1.,2.,3.,2.,1.])
131
w = w / np.sum(w)
132
133
'''print(residual_resample(w))
134
import matplotlib as mpl
135
cmap = mpl.colors.ListedColormap([[0., .4, 1.],
136
[0., .8, 1.],
137
[1., .8, 0.],
138
[1., .4, 0.]]*5)
139
bounds = np.array([1., 2., 4, 7, 8]*3)
140
bounds /= sum(bounds)
141
a = np.cumsum(bounds)
142
143
fig = plt.figure(figsize=(8,3))
144
ax = fig.add_axes([0.05, 0.475, 0.9, 0.15])
145
norm = mpl.colors.BoundaryNorm(a, cmap.N)
146
bar = mpl.colorbar.ColorbarBase(ax, cmap=cmap,
147
norm=norm,
148
drawedges=False,
149
spacing='proportional',
150
orientation='horizontal')
151
bar.set_ticks([])
152
plt.show()'''
153