Commit e1f76237 authored by Jan Trmal's avatar Jan Trmal
Browse files

windows fixes -- resolving issues with incrrectly behaving expf/exp(float)...

windows fixes -- resolving issues with incrrectly behaving expf/exp(float) under MSVC2013, plus some other improvements
parent db63ae29
......@@ -55,7 +55,7 @@ OnlinePaSource::OnlinePaSource(const uint32 timeout,
report_interval_(report_interval), nread_calls_(0),
noverflows_(0), samples_lost_(0) {
using namespace std;
int32 rb_bits = static_cast<int32>(ceil(log(rb_size) / log(2)));
int32 rb_bits = static_cast<int32>(ceil(Log(rb_size) / Log(2)));
if (rb_bits > 30) // ok, this limit is somewhat arbitrary
throw invalid_argument("PortAudio ring buffer too large!");
rb_size_ = 1 << rb_bits;
......
......@@ -31,7 +31,7 @@ DecodableDiagGmmScaledOnline::DecodableDiagGmmScaledOnline(
feat_dim_(input_feats->Dim()), cur_feats_(feat_dim_),
cur_frame_(-1) {
int32 num_pdfs = trans_model_.NumPdfs();
cache_.resize(num_pdfs, std::pair<int32,BaseFloat>(-1, 0.0));
cache_.resize(num_pdfs, std::pair<int32,BaseFloat>(-1, 0.0f));
}
void DecodableDiagGmmScaledOnline::CacheFrame(int32 frame) {
......
......@@ -700,7 +700,7 @@ void AmSgmm::ComputeNormalizers() {
KALDI_LOG << "Entropy of weights in substates is "
<< (entropy_sum / entropy_count) << " over " << entropy_count
<< " substates, equivalent to perplexity of "
<< (exp(entropy_sum /entropy_count));
<< (Exp(entropy_sum /entropy_count));
KALDI_LOG << "Done computing normalizers";
}
......@@ -709,7 +709,7 @@ void AmSgmm::ComputeNormalizersInternal(int32 num_threads, int32 thread,
int32 *entropy_count,
double *entropy_sum) {
BaseFloat DLog2pi = FeatureDim() * log(2 * M_PI);
BaseFloat DLog2pi = FeatureDim() * Log(2 * M_PI);
Vector<BaseFloat> log_det_Sigma(NumGauss());
for (int32 i = 0; i < NumGauss(); i++) {
......@@ -740,7 +740,7 @@ void AmSgmm::ComputeNormalizersInternal(int32 num_threads, int32 thread,
{ // DIAGNOSTIC CODE
(*entropy_count)++;
for (int32 i = 0; i < NumGauss(); i++) {
(*entropy_sum) -= log_w_jm(m, i) * exp(log_w_jm(m, i));
(*entropy_sum) -= log_w_jm(m, i) * Exp(log_w_jm(m, i));
}
}
}
......@@ -753,7 +753,7 @@ void AmSgmm::ComputeNormalizersInternal(int32 num_threads, int32 thread,
for (int32 m = 0; m < NumSubstates(j); m++) {
// mu_{jmi} * \Sigma_{i}^{-1} * mu_{jmi}
BaseFloat mu_SigmaInv_mu = VecVec(mu_jmi.Row(m), SigmaInv_mu.Row(m));
BaseFloat logc = log(c_[j](m));
BaseFloat logc = Log(c_[j](m));
// Suggestion: Both mu_jmi and SigmaInv_mu could
// have been computed at once for i,
......@@ -793,7 +793,7 @@ void AmSgmm::ComputeNormalizersNormalized(
}
KALDI_LOG << "Computing normalizers [normalized]";
BaseFloat DLog2pi = FeatureDim() * log(2 * M_PI);
BaseFloat DLog2pi = FeatureDim() * Log(2 * M_PI);
Vector<BaseFloat> mu_jmi(FeatureDim());
Vector<BaseFloat> SigmaInv_mu(FeatureDim());
Vector<BaseFloat> log_det_Sigma(NumGauss());
......@@ -814,7 +814,7 @@ void AmSgmm::ComputeNormalizersNormalized(
n_[j].Resize(NumGauss(), NumSubstates(j));
for (int32 m = 0; m < NumSubstates(j); m++) {
BaseFloat logc = log(c_[j](m));
BaseFloat logc = Log(c_[j](m));
// (in logs): w_jm = softmax([w_{k1}^T ... w_{kD}^T] * v_{jkm}) eq.(7)
log_w_jm.AddMatVec(1.0, w_, kNoTrans, v_[j].Row(m), 0.0);
......@@ -824,8 +824,8 @@ void AmSgmm::ComputeNormalizersNormalized(
const std::vector<int32> &this_set(normalize_sets[n]);
double sum = 0.0;
for (int32 p = 0; p < this_set.size(); p++)
sum += exp(log_w_jm(this_set[p]));
double offset = -log(sum); // add "offset", to normalize weights.
sum += Exp(log_w_jm(this_set[p]));
double offset = -Log(sum); // add "offset", to normalize weights.
for (int32 p = 0; p < this_set.size(); p++)
log_w_jm(this_set[p]) += offset;
}
......
......@@ -22,10 +22,13 @@
#include "sgmm/estimate-am-sgmm.h"
#include "sgmm/estimate-am-sgmm-multi.h"
#include "util/kaldi-io.h"
#include "base/kaldi-math.h"
using kaldi::AmSgmm;
using kaldi::MleAmSgmmAccs;
using kaldi::BaseFloat;
using kaldi::Exp;
namespace ut = kaldi::unittest;
// Tests the MleAmSgmmUpdaterMulti (and MleAmSgmmGlobalAccs) classes.
......@@ -122,7 +125,7 @@ void UnitTestEstimateSgmm() {
for (int32 m = 0; m < num_feat_comp; ++m) {
for (int32 d= 0; d < dim; d++) {
means(m, d) = kaldi::RandGauss();
vars(m, d) = exp(kaldi::RandGauss()) + 1e-2;
vars(m, d) = Exp(kaldi::RandGauss()) + 1e-2;
}
}
// Now generate random features with those means and variances.
......
......@@ -22,10 +22,13 @@
#include "sgmm/am-sgmm.h"
#include "sgmm/estimate-am-sgmm.h"
#include "util/kaldi-io.h"
#include "base/kaldi-math.h"
using kaldi::AmSgmm;
using kaldi::MleAmSgmmAccs;
using kaldi::BaseFloat;
using kaldi::Exp;
namespace ut = kaldi::unittest;
// Tests the Read() and Write() methods for the accumulators, in both binary
......@@ -137,7 +140,7 @@ void UnitTestEstimateSgmm() {
for (int32 m = 0; m < num_feat_comp; m++) {
for (int32 d= 0; d < dim; d++) {
means(m, d) = kaldi::RandGauss();
vars(m, d) = exp(kaldi::RandGauss()) + 1e-2;
vars(m, d) = Exp(kaldi::RandGauss()) + 1e-2;
}
}
// Now generate random features with those means and variances.
......
......@@ -1267,7 +1267,7 @@ void MleAmSgmmUpdater::ComputeMPrior(AmSgmm *model) {
Matrix<double> MDiff(Ddim, Sdim);
for (int32 iter = 0; iter < update_options_.map_M_prior_iters; iter++) {
{ // diagnostic block.
double prior_like = -0.5 * nGaussians * (Ddim * Sdim * log(2 * M_PI)
double prior_like = -0.5 * nGaussians * (Ddim * Sdim * Log(2 * M_PI)
+ Sdim * (-model->row_cov_inv_.LogPosDefDet())
+ Ddim * (-model->col_cov_inv_.LogPosDefDet()));
for (int32 i = 0; i < nGaussians; i++) {
......@@ -1639,7 +1639,7 @@ double MleAmSgmmUpdater::UpdateWSequential(
double this_unnormalized_weight = VecVec(w_i, model->v_[j].Row(m));
double normalizer = weight_tots[j](m);
double this_log_w = this_unnormalized_weight - normalizer,
this_w = exp(this_log_w),
this_w = Exp(this_log_w),
substate_count = gamma_jm[j](m),
this_count = accs.gamma_[j](m, i);
......@@ -2000,7 +2000,7 @@ double MleAmSgmmUpdater::UpdateSubstateWeights(
cur_weight = 1.0e-10; // future work(arnab): remove magic numbers
}
model->c_[j](m) = smoothed_occs(m) / gamma_j_sm;
objf_impr += log(model->c_[j](m) / cur_weight) * occs(m);
objf_impr += Log(model->c_[j](m) / cur_weight) * occs(m);
}
tot_gamma += gamma_j_(j);
}
......
......@@ -20,6 +20,7 @@
#include <vector>
#include "base/kaldi-math.h"
#include "gmm/model-test-common.h"
#include "sgmm/am-sgmm.h"
#include "sgmm/fmllr-sgmm.h"
......@@ -30,6 +31,8 @@ using kaldi::int32;
using kaldi::BaseFloat;
using kaldi::Vector;
using kaldi::Matrix;
using kaldi::Exp;
namespace ut = kaldi::unittest;
void ApplyFmllrXform(const kaldi::VectorBase<BaseFloat> &in,
......@@ -206,7 +209,7 @@ void TestSgmmFmllr() {
for (int32 m = 0; m < num_feat_comp; m++) {
for (int32 d= 0; d < dim; d++) {
means(m, d) = kaldi::RandGauss();
vars(m, d) = exp(kaldi::RandGauss()) + 1e-2;
vars(m, d) = Exp(kaldi::RandGauss()) + 1e-2;
}
}
// Now generate random features with those means and variances.
......
......@@ -77,7 +77,7 @@ BaseFloat SgmmClusterable::Objf() const {
if (prob > 0.0) { // Note: prob could be zero due to underflow-- this
// happened! [we can get tiny values due to floating-point roundoff
// while subtracting clusterable objects].
ans += gamma * log(gamma / tot_gamma);
ans += gamma * Log(gamma / tot_gamma);
}
}
tot_gamma2 += gamma;
......
......@@ -559,7 +559,7 @@ BaseFloat AmSgmm2::LogLikelihood(const Sgmm2PerFrameDerivedVars &per_frame_vars,
}
BaseFloat log_like = substate_cache.remaining_log_like
+ log(VecVec(substate_cache.likes, c_[j2]));
+ Log(VecVec(substate_cache.likes, c_[j2]));
if (random_test)
KALDI_ASSERT(ApproxEqual(pdf_cache.log_like, log_like));
......@@ -589,7 +589,7 @@ AmSgmm2::ComponentPosteriors(const Sgmm2PerFrameDerivedVars &per_frame_vars,
BaseFloat tot_like = post->Sum();
KALDI_ASSERT(tot_like != 0.0); // note: not valid to have zero weights.
loglike += log(tot_like);
loglike += Log(tot_like);
post->Scale(1.0 / tot_like); // so "post" now sums to one, and "loglike"
// contains the correct log-likelihood of the data given the pdf.
......@@ -859,7 +859,7 @@ void AmSgmm2::ComputeNormalizers() {
KALDI_LOG << "Entropy of weights in substates is "
<< (entropy_sum / entropy_count) << " over " << entropy_count
<< " substates, equivalent to perplexity of "
<< (exp(entropy_sum /entropy_count));
<< (Exp(entropy_sum /entropy_count));
KALDI_LOG << "Done computing normalizers";
}
......@@ -868,7 +868,7 @@ void AmSgmm2::ComputeNormalizersInternal(int32 num_threads, int32 thread,
int32 *entropy_count,
double *entropy_sum) {
BaseFloat DLog2pi = FeatureDim() * log(2 * M_PI);
BaseFloat DLog2pi = FeatureDim() * Log(2 * M_PI);
Vector<BaseFloat> log_det_Sigma(NumGauss());
for (int32 i = 0; i < NumGauss(); i++) {
......@@ -902,7 +902,7 @@ void AmSgmm2::ComputeNormalizersInternal(int32 num_threads, int32 thread,
{ // DIAGNOSTIC CODE
(*entropy_count)++;
for (int32 i = 0; i < NumGauss(); i++) {
(*entropy_sum) -= log_w_jm(m, i) * exp(log_w_jm(m, i));
(*entropy_sum) -= log_w_jm(m, i) * Exp(log_w_jm(m, i));
}
}
}
......@@ -952,7 +952,7 @@ BaseFloat AmSgmm2::GetDjms(int32 j1, int32 m,
log_d.AddMatVec(1.0, w_jmi_[j1], kNoTrans, spk_vars->b_is, 0.0);
log_d.ApplyLog();
}
return exp(log_d(m));
return Exp(log_d(m));
}
......
......@@ -19,6 +19,7 @@
// See the Apache 2 License for the specific language governing permissions and
// limitations under the License.
#include "base/kaldi-math.h"
#include "gmm/model-test-common.h"
#include "sgmm2/am-sgmm2.h"
#include "sgmm2/estimate-am-sgmm2.h"
......@@ -28,6 +29,8 @@ using kaldi::AmSgmm2;
using kaldi::MleAmSgmm2Accs;
using kaldi::int32;
using kaldi::BaseFloat;
using kaldi::Exp;
namespace ut = kaldi::unittest;
// Tests the Read() and Write() methods for the accumulators, in both binary
......@@ -143,7 +146,7 @@ void UnitTestEstimateSgmm2() {
for (int32 m = 0; m < num_feat_comp; m++) {
for (int32 d= 0; d < dim; d++) {
means(m, d) = kaldi::RandGauss();
vars(m, d) = exp(kaldi::RandGauss()) + 1e-2;
vars(m, d) = Exp(kaldi::RandGauss()) + 1e-2;
}
}
// Now generate random features with those means and variances.
......
......@@ -1108,7 +1108,7 @@ void MleAmSgmm2Updater::ComputeMPrior(AmSgmm2 *model) {
Matrix<double> MDiff(Ddim, Sdim);
for (int32 iter = 0; iter < options_.map_M_prior_iters; iter++) {
{ // diagnostic block.
double prior_like = -0.5 * nGaussians * (Ddim * Sdim * log(2 * M_PI)
double prior_like = -0.5 * nGaussians * (Ddim * Sdim * Log(2 * M_PI)
+ Sdim * (-model->row_cov_inv_.LogPosDefDet())
+ Ddim * (-model->col_cov_inv_.LogPosDefDet()));
for (int32 i = 0; i < nGaussians; i++) {
......@@ -1695,7 +1695,7 @@ double MleAmSgmm2Updater::UpdateSubstateWeights(
cur_weight = 1.0e-10; // future work(arnab): remove magic numbers
}
model->c_[j2](m) = smoothed_occs(m) / gamma_j_sm;
objf_impr += log(model->c_[j2](m) / cur_weight) * occs(m);
objf_impr += Log(model->c_[j2](m) / cur_weight) * occs(m);
}
}
KALDI_LOG << "**Overall objf impr for c is " << (objf_impr/tot_gamma)
......
......@@ -20,6 +20,7 @@
#include <vector>
#include "base/kaldi-math.h"
#include "gmm/model-test-common.h"
#include "sgmm2/am-sgmm2.h"
#include "sgmm2/fmllr-sgmm2.h"
......@@ -30,6 +31,8 @@ using kaldi::int32;
using kaldi::BaseFloat;
using kaldi::Vector;
using kaldi::Matrix;
using kaldi::Exp;
namespace ut = kaldi::unittest;
void ApplyFmllrXform(const kaldi::VectorBase<BaseFloat> &in,
......@@ -217,7 +220,7 @@ void TestSgmm2Fmllr() {
for (int32 m = 0; m < num_feat_comp; m++) {
for (int32 d= 0; d < dim; d++) {
means(m, d) = kaldi::RandGauss();
vars(m, d) = exp(kaldi::RandGauss()) + 1e-2;
vars(m, d) = Exp(kaldi::RandGauss()) + 1e-2;
}
}
// Now generate random features with those means and variances.
......
......@@ -124,9 +124,9 @@ static void ComputeGconsts(const VectorBase<BaseFloat> &weights,
for (int32 gauss = 0; gauss < num_gauss; gauss++) {
KALDI_ASSERT(weights(gauss) >= 0); // Cannot have negative weights.
BaseFloat gc = log(weights(gauss)) + offset; // May be -inf if weights == 0
BaseFloat gc = Log(weights(gauss)) + offset; // May be -inf if weights == 0
for (int32 d = 0; d < dim; d++) {
gc += 0.5 * log(inv_vars(gauss, d)) - 0.5 * means(gauss, d)
gc += 0.5 * Log(inv_vars(gauss, d)) - 0.5 * means(gauss, d)
* means(gauss, d) * inv_vars(gauss, d); // diff from DiagGmm version.
}
......
......@@ -34,10 +34,10 @@ void InitRandomGmm (DiagGmm *gmm_in) {
Vector<BaseFloat> weights(num_gauss);
for (int32 i = 0; i < num_gauss; i++) {
for (int32 j = 0; j < dim; j++) {
inv_vars(i, j) = exp(RandGauss() * (1.0 / (1 + j)));
inv_vars(i, j) = Exp(RandGauss() * (1.0 / (1 + j)));
means(i, j) = RandGauss() * (1.0 / (1 + j));
}
weights(i) = exp(RandGauss());
weights(i) = Exp(RandGauss());
}
weights.Scale(1.0 / weights.Sum());
gmm.SetWeights(weights);
......
......@@ -221,9 +221,9 @@ void FmllrInnerUpdate(SpMatrix<double> &inv_G,
double discr = std::sqrt(e2 * e2 + 4 * e1 * beta);
double alpha1 = (-e2 + discr) / (2 * e1);
double alpha2 = (-e2 - discr) / (2 * e1);
double auxf1 = beta * std::log(std::abs(alpha1 * e1 + e2)) -
double auxf1 = beta * Log(std::abs(alpha1 * e1 + e2)) -
0.5 * alpha1 * alpha1 * e1;
double auxf2 = beta * std::log(std::abs(alpha2 * e1 + e2)) -
double auxf2 = beta * Log(std::abs(alpha2 * e1 + e2)) -
0.5 * alpha2 * alpha2 * e1;
double alpha = (auxf1 > auxf2) ? alpha1 : alpha2;
......
......@@ -36,10 +36,10 @@ void InitRandomGmm (DiagGmm *gmm_in) {
Vector<BaseFloat> weights(num_gauss);
for (int32 i = 0; i < num_gauss; i++) {
for (int32 j = 0; j < dim; j++) {
inv_vars(i, j) = exp(RandGauss() * (1.0 / (1 + j)));
inv_vars(i, j) = Exp(RandGauss() * (1.0 / (1 + j)));
means(i, j) = RandGauss() * (1.0 / (1 + j));
}
weights(i) = exp(RandGauss());
weights(i) = Exp(RandGauss());
}
weights.Scale(1.0 / weights.Sum());
gmm.SetWeights(weights);
......
......@@ -105,12 +105,12 @@ void MlltAccs::Update(double beta,
// for hidden markov models, eq. (22)),
// row = G_i^{-1} cofactor sqrt(beta / cofactor^T G_i^{-1} cofactor). (1)
// here, "row" and "cofactor" are considered as column vectors.
double objf_before = beta * log(std::abs(VecVec(row, cofactor)))
double objf_before = beta * Log(std::abs(VecVec(row, cofactor)))
-0.5 * VecSpVec(row, G[i], row);
// do eq. (1) above:
row.AddSpVec(std::sqrt(beta / VecSpVec(cofactor, Ginv[i], cofactor)),
Ginv[i], cofactor, 0.0);
double objf_after = beta * log(std::abs(VecVec(row, cofactor)))
double objf_after = beta * Log(std::abs(VecVec(row, cofactor)))
-0.5 * VecSpVec(row, G[i], row);
if (objf_after < objf_before - fabs(objf_before)*0.00001)
KALDI_ERR << "Objective decrease in MLLT update.";
......
......@@ -67,7 +67,7 @@ rand_diag_gmm(size_t num_comp, size_t dim, DiagGmm *gmm) {
weights(m) = kaldi::RandUniform();
for (size_t d= 0; d < dim; d++) {
means(m, d) = kaldi::RandGauss();
vars(m, d) = exp(kaldi::RandGauss()) + 1e-5;
vars(m, d) = Exp(kaldi::RandGauss()) + 1e-5;
}
tot_weight += weights(m);
}
......
......@@ -98,7 +98,7 @@ generate_features(cova_type covariance_type,
// random diagonal covariance for gaussian j
Sj.SetZero();
for (size_t d = 0; d < dim; d++) {
Sj(d, d) = 2*exp(RandGauss());
Sj(d, d) = 2*Exp(RandGauss());
}
}
if (covariance_type == full) {
......
......@@ -104,8 +104,8 @@ bool IsToken(const std::string &token) {
size_t l = token.length();
if (l == 0) return false;
for (size_t i = 0; i < l; i++) {
char c = token[i];
if ( (!isprint(c) || isspace(c)) && (isascii(c) || c == (char)255) ) return false;
unsigned char c = token[i];
if ( (!isprint(c) || isspace(c)) && (isascii(c) || c == (unsigned char)255) ) return false;
// The "&& (isascii(c) || c == 255)" was added so that we won't reject non-ASCII
// characters such as French characters with accents [except for 255 which is
// "nbsp", a form of space].
......@@ -159,11 +159,65 @@ bool IsLine(const std::string &line) {
return true;
}
inline bool starts_with(const std::string &in, const std::string &prefix) {
return in.substr(0, prefix.size()) == prefix;
}
inline bool stricmp(const std::string &in, const std::string &prefix) {
int ret = _stricmp(in.c_str(), prefix.c_str());
return ret == 0;
}
inline bool is_nan_text(const std::string &in, const std::string &prefix) {
if (in.size() < prefix.size())
return false;
if (stricmp(in, prefix))
return true;
for (int i = 0; i < prefix.size(); ++i)
if (tolower(in[i]) != tolower(prefix[i]))
return false;
for (int i = prefix.size(); i < in.size(); ++i)
if (!isalpha(in[i]) && (in[i] != '_'))
return false;
return true;
}
template<typename T>
bool convert_special_number(const std::string &str, T *out) {
if (stricmp(str, "infinity") || stricmp(str, "inf") || starts_with(str, "1.#INF")) {
*out = std::numeric_limits<T>::infinity();
return true;
} else if (stricmp(str, "-infinity") || stricmp(str, "-inf") || starts_with(str, "-1.#INF")) {
*out = -std::numeric_limits<T>::infinity();
return true;
} else if (is_nan_text(str, "nan") || starts_with(str, "1.#QNAN")) {
*out = std::numeric_limits<T>::quiet_NaN();
return true;
} else if (is_nan_text(str, "-nan") || starts_with(str, "-1.#QNAN")) {
*out = -std::numeric_limits<T>::quiet_NaN();
return true;
}
return false;
}
bool ConvertStringToReal(const std::string &str,
double *out) {
const char *this_str = str.c_str();
char *end = NULL;
errno = 0;
#if defined(_MSC_VER)
// TODO: check if the new MSVC already supports it
// depending on claims of the C++11 support, it should have
if (convert_special_number(str, out))
return true;
#endif // defined(_MSC_VER)
double d = KALDI_STRTOD(this_str, &end);
if (end != this_str)
while (isspace(*end)) end++;
......@@ -178,6 +232,14 @@ bool ConvertStringToReal(const std::string &str,
const char *this_str = str.c_str();
char *end = NULL;
errno = 0;
#ifdef _MSC_VER
// TODO: check if the new MSVC already supports it
// depending on claims of the C++11 support, it should have
if (convert_special_number(str, out))
return true;
#endif // _MSC_VER
float f = KALDI_STRTOF(this_str, &end);
if (end != this_str)
while (isspace(*end)) end++;
......
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