Commit 30a3e352 authored by Davis King's avatar Davis King

merged

parents 83057123 d7647e83
...@@ -35,19 +35,30 @@ if (UNIX OR MINGW) ...@@ -35,19 +35,30 @@ if (UNIX OR MINGW)
message(STATUS "Searching for BLAS and LAPACK") message(STATUS "Searching for BLAS and LAPACK")
if (BUILDING_MATLAB_MEX_FILE) if (BUILDING_MATLAB_MEX_FILE)
find_library(MATLAB_BLAS_LIBRARY mwblas PATHS ${MATLAB_LIB_FOLDERS} ) # # This commented out stuff would link directly to MATLAB's built in
find_library(MATLAB_LAPACK_LIBRARY mwlapack PATHS ${MATLAB_LIB_FOLDERS} ) # BLAS and LAPACK. But it's better to not link to anything and do a
if (MATLAB_BLAS_LIBRARY AND MATLAB_LAPACK_LIBRARY) #find_library(MATLAB_BLAS_LIBRARY mwblas PATHS ${MATLAB_LIB_FOLDERS} )
#find_library(MATLAB_LAPACK_LIBRARY mwlapack PATHS ${MATLAB_LIB_FOLDERS} )
#if (MATLAB_BLAS_LIBRARY AND MATLAB_LAPACK_LIBRARY)
# add_subdirectory(external/cblas)
# set(blas_libraries ${MATLAB_BLAS_LIBRARY} cblas )
# set(lapack_libraries ${MATLAB_LAPACK_LIBRARY} )
# set(blas_found 1)
# set(lapack_found 1)
# message(STATUS "Found MATLAB's BLAS and LAPACK libraries")
#endif()
# We need cblas since MATLAB doesn't provide cblas symbols.
add_subdirectory(external/cblas) add_subdirectory(external/cblas)
set(blas_libraries ${MATLAB_BLAS_LIBRARY} cblas ) set(blas_libraries cblas )
set(lapack_libraries ${MATLAB_LAPACK_LIBRARY} )
set(blas_found 1) set(blas_found 1)
set(lapack_found 1) set(lapack_found 1)
message(STATUS "Found MATLAB's BLAS and LAPACK libraries") message(STATUS "Will link with MATLAB's BLAS and LAPACK at runtime (hopefully!)")
endif()
# Don't try to link to anything other than MATLAB's own internal blas
# and lapack libraries because doing so generally upsets MATLAB. So ## Don't try to link to anything other than MATLAB's own internal blas
# we just end here no matter what. ## and lapack libraries because doing so generally upsets MATLAB. So
## we just end here no matter what.
return() return()
endif() endif()
......
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
#include "isotonic_regression_abstract.h" #include "isotonic_regression_abstract.h"
#include <vector> #include <vector>
#include <utility>
namespace dlib namespace dlib
{ {
...@@ -22,22 +23,13 @@ namespace dlib ...@@ -22,22 +23,13 @@ namespace dlib
iterator obegin iterator obegin
) )
{ {
for (auto i = begin; i != end; ++i) do_isotonic_regression(begin, end);
{
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();
}
}
// unpack results to output // unpack blocks to output
for (auto& block : blocks) for (auto& block : blocks)
{ {
for (size_t k = 0; k < block.num; ++k) for (size_t k = 0; k < block.num; ++k)
*obegin++ = block.avg; set_val(*obegin++, block.avg);
} }
blocks.clear(); blocks.clear();
...@@ -47,8 +39,108 @@ namespace dlib ...@@ -47,8 +39,108 @@ namespace dlib
std::vector<double>& vect std::vector<double>& vect
) { (*this)(vect.begin(), vect.end(), vect.begin()); } ) { (*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: 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 struct block_t
{ {
......
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
#ifdef DLIB_ISOTONIC_ReGRESSION_ABSTRACT_H_ #ifdef DLIB_ISOTONIC_ReGRESSION_ABSTRACT_H_
#include <vector> #include <vector>
#include <utility>
namespace dlib namespace dlib
{ {
...@@ -31,9 +32,10 @@ namespace dlib ...@@ -31,9 +32,10 @@ namespace dlib
); );
/*! /*!
requires requires
- [begin,end) is an iterator range of float or doubles. - [begin,end) is an iterator range of float or doubles or a range of
- obegin points to an iterator range at least std::distance(begin,end) in std::pair<T,double> or std::pair<T,float> where T an be anything.
size which is capable of storing double or float values. - 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 ensures
- Given the range of real values stored in [begin,end), this method performs isotonic regression - 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: on this data and writes the results to obegin. To be specific:
...@@ -44,6 +46,10 @@ namespace dlib ...@@ -44,6 +46,10 @@ namespace dlib
OUT[i] <= OUT[i+1], i.e. that OUT is monotonic. 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. - It is OK for [begin,end) to overlap with the range pointed to by obegin.
That is, this function can run in-place. 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() ( void operator() (
...@@ -56,6 +62,63 @@ namespace dlib ...@@ -56,6 +62,63 @@ namespace dlib
- #vect.size() == vect.size() - #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()
!*/
}; };
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment