Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in
Toggle navigation
D
dlib
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
钟尚武
dlib
Commits
306cd1a2
Commit
306cd1a2
authored
Mar 07, 2018
by
Davis King
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Improved isotonic_regression class.
parent
cb481f27
Show whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
170 additions
and
15 deletions
+170
-15
isotonic_regression.h
dlib/optimization/isotonic_regression.h
+104
-12
isotonic_regression_abstract.h
dlib/optimization/isotonic_regression_abstract.h
+66
-3
No files found.
dlib/optimization/isotonic_regression.h
View file @
306cd1a2
...
...
@@ -5,6 +5,7 @@
#include "isotonic_regression_abstract.h"
#include <vector>
#include <utility>
namespace
dlib
{
...
...
@@ -22,22 +23,13 @@ namespace dlib
iterator
obegin
)
{
for
(
auto
i
=
begin
;
i
!=
end
;
++
i
)
{
blocks
.
emplace_back
(
*
i
);
while
(
blocks
.
size
()
>
1
&&
prev_block
().
avg
>
current_block
().
avg
)
{
// merge the last two blocks.
prev_block
()
=
prev_block
()
+
current_block
();
blocks
.
pop_back
();
}
}
do_isotonic_regression
(
begin
,
end
);
// unpack
result
s to output
// unpack
block
s to output
for
(
auto
&
block
:
blocks
)
{
for
(
size_t
k
=
0
;
k
<
block
.
num
;
++
k
)
*
obegin
++
=
block
.
avg
;
set_val
(
*
obegin
++
,
block
.
avg
)
;
}
blocks
.
clear
();
...
...
@@ -47,8 +39,108 @@ namespace dlib
std
::
vector
<
double
>&
vect
)
{
(
*
this
)(
vect
.
begin
(),
vect
.
end
(),
vect
.
begin
());
}
template
<
typename
T
,
typename
U
>
void
operator
()
(
std
::
vector
<
std
::
pair
<
T
,
U
>>&
vect
)
{
(
*
this
)(
vect
.
begin
(),
vect
.
end
(),
vect
.
begin
());
}
template
<
typename
const_iterator
,
typename
iterator
>
void
fit_with_linear_output_interpolation
(
const_iterator
begin
,
const_iterator
end
,
iterator
obegin
)
{
do_isotonic_regression
(
begin
,
end
);
// Unpack blocks to output, but here instead of producing the step function
// output we linearly interpolate. Note that this actually fits the data less
// than the step-function, but in many applications might be closer to what you
// really when when using isotonic_regression than the step function.
for
(
size_t
i
=
0
;
i
<
blocks
.
size
();
++
i
)
{
auto
&
block
=
blocks
[
i
];
double
prev
=
(
blocks
.
front
().
avg
+
block
.
avg
)
/
2
;
if
(
i
>
0
)
prev
=
(
blocks
[
i
-
1
].
avg
+
block
.
avg
)
/
2
;
double
next
=
(
blocks
.
back
().
avg
+
block
.
avg
)
/
2
;
if
(
i
+
1
<
blocks
.
size
())
next
=
(
blocks
[
i
+
1
].
avg
+
block
.
avg
)
/
2
;
for
(
size_t
k
=
0
;
k
<
block
.
num
;
++
k
)
{
const
auto
mid
=
block
.
num
/
2
.
0
;
if
(
k
<
mid
)
{
const
double
alpha
=
k
/
mid
;
set_val
(
*
obegin
++
,
(
1
-
alpha
)
*
prev
+
alpha
*
block
.
avg
);
}
else
{
const
double
alpha
=
k
/
mid
-
1
;
set_val
(
*
obegin
++
,
alpha
*
next
+
(
1
-
alpha
)
*
block
.
avg
);
}
}
}
blocks
.
clear
();
}
void
fit_with_linear_output_interpolation
(
std
::
vector
<
double
>&
vect
)
{
fit_with_linear_output_interpolation
(
vect
.
begin
(),
vect
.
end
(),
vect
.
begin
());
}
template
<
typename
T
,
typename
U
>
void
fit_with_linear_output_interpolation
(
std
::
vector
<
std
::
pair
<
T
,
U
>>&
vect
)
{
fit_with_linear_output_interpolation
(
vect
.
begin
(),
vect
.
end
(),
vect
.
begin
());
}
private
:
template
<
typename
const_iterator
>
void
do_isotonic_regression
(
const_iterator
begin
,
const_iterator
end
)
{
blocks
.
clear
();
// Do the actual isotonic regression. The output is a step-function and is
// stored in the vector of blocks.
for
(
auto
i
=
begin
;
i
!=
end
;
++
i
)
{
blocks
.
emplace_back
(
get_val
(
*
i
));
while
(
blocks
.
size
()
>
1
&&
prev_block
().
avg
>
current_block
().
avg
)
{
// merge the last two blocks.
prev_block
()
=
prev_block
()
+
current_block
();
blocks
.
pop_back
();
}
}
}
template
<
typename
T
>
static
double
get_val
(
const
T
&
v
)
{
return
v
;}
template
<
typename
T
,
typename
U
>
static
double
get_val
(
const
std
::
pair
<
T
,
U
>&
v
)
{
return
v
.
second
;}
template
<
typename
T
>
static
void
set_val
(
T
&
v
,
double
val
)
{
v
=
val
;}
template
<
typename
T
,
typename
U
>
static
void
set_val
(
std
::
pair
<
T
,
U
>&
v
,
double
val
)
{
v
.
second
=
val
;}
struct
block_t
{
...
...
dlib/optimization/isotonic_regression_abstract.h
View file @
306cd1a2
...
...
@@ -4,6 +4,7 @@
#ifdef DLIB_ISOTONIC_ReGRESSION_ABSTRACT_H_
#include <vector>
#include <utility>
namespace
dlib
{
...
...
@@ -31,9 +32,10 @@ namespace dlib
);
/*!
requires
- [begin,end) is an iterator range of float or doubles.
- obegin points to an iterator range at least std::distance(begin,end) in
size which is capable of storing double or float values.
- [begin,end) is an iterator range of float or doubles or a range of
std::pair<T,double> or std::pair<T,float> where T an be anything.
- obegin points to an iterator range at least std::distance(begin,end).
- obegin points to an iterator range of objects of type float, double, std::pair<T,float>, or std::pair<T,double>.
ensures
- Given the range of real values stored in [begin,end), this method performs isotonic regression
on this data and writes the results to obegin. To be specific:
...
...
@@ -44,6 +46,10 @@ namespace dlib
OUT[i] <= OUT[i+1], i.e. that OUT is monotonic.
- It is OK for [begin,end) to overlap with the range pointed to by obegin.
That is, this function can run in-place.
- Note that when the inputs or outputs are std::pairs this algorithm only
looks at the .second field of the pair. It therefore still treats these
iterator ranges as ranges of reals since it only looks at the .second
field, which is a real number. The .first field is entirely ignored.
!*/
void
operator
()
(
...
...
@@ -56,6 +62,63 @@ namespace dlib
- #vect.size() == vect.size()
!*/
template
<
typename
T
,
typename
U
>
void
operator
()
(
std
::
vector
<
std
::
pair
<
T
,
U
>>&
vect
)
{
(
*
this
)(
vect
.
begin
(),
vect
.
end
(),
vect
.
begin
());
}
/*!
ensures
- performs in-place isotonic regression. Therefore, #vect will contain the
isotonic regression of vect.
- #vect.size() == vect.size()
!*/
template
<
typename
const_iterator
,
typename
iterator
>
void
fit_with_linear_output_interpolation
(
const_iterator
begin
,
const_iterator
end
,
iterator
obegin
);
/*!
requires
- [begin,end) is an iterator range of float or doubles or a range of
std::pair<T,double> or std::pair<T,float> where T an be anything.
- obegin points to an iterator range at least std::distance(begin,end).
- obegin points to an iterator range of objects of type float, double, std::pair<T,float>, or std::pair<T,double>.
ensures
- This function behaves just like (*this)(begin,end,obegin) except that the
output is interpolated. To explain, not that the optimal output of
isotonic regression is a step function. However, in many applications
that isn't really what you want. You want something smoother. So
fit_with_linear_output_interpolation() does isotonic regression and then
linearly interpolates the step function into a piecewise linear function.
!*/
void
fit_with_linear_output_interpolation
(
std
::
vector
<
double
>&
vect
)
{
fit_with_linear_output_interpolation
(
vect
.
begin
(),
vect
.
end
(),
vect
.
begin
());
}
/*!
ensures
- performs in-place isotonic regression. Therefore, #vect will contain the
isotonic regression of vect.
- #vect.size() == vect.size()
!*/
template
<
typename
T
,
typename
U
>
void
fit_with_linear_output_interpolation
(
std
::
vector
<
std
::
pair
<
T
,
U
>>&
vect
)
{
fit_with_linear_output_interpolation
(
vect
.
begin
(),
vect
.
end
(),
vect
.
begin
());
}
/*!
ensures
- performs in-place isotonic regression. Therefore, #vect will contain the
isotonic regression of vect.
- #vect.size() == vect.size()
!*/
};
}
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment