46 double dFMin,
double dFMax,
51 const int nAtoms = 2 * iNFreqs;
52 MatrixXd dict = MatrixXd::Zero(nAtoms, iNSamples);
54 VectorXd timeVec(iNSamples);
55 for (
int t = 0; t < iNSamples; ++t) {
56 timeVec(t) =
static_cast<double>(t) / dSFreq;
60 for (
int f = 0; f < iNFreqs; ++f) {
63 double logMin = std::log(dFMin);
64 double logMax = std::log(dFMax);
65 freq = std::exp(logMin + (logMax - logMin) * f / (iNFreqs - 1));
67 freq = (dFMin + dFMax) / 2.0;
71 double sigma = 3.0 / (2.0 *
M_PI * freq);
73 double tCenter = timeVec(iNSamples / 2);
75 for (
int t = 0; t < iNSamples; ++t) {
76 double dt = timeVec(t) - tCenter;
77 double envelope = std::exp(-0.5 * dt * dt / (sigma * sigma));
78 dict(2 * f, t) = envelope * std::cos(2.0 *
M_PI * freq * timeVec(t));
79 dict(2 * f + 1, t) = envelope * std::sin(2.0 *
M_PI * freq * timeVec(t));
83 double normCos = dict.row(2 * f).norm();
84 if (normCos > 1e-12) dict.row(2 * f) /= normCos;
86 double normSin = dict.row(2 * f + 1).norm();
87 if (normSin > 1e-12) dict.row(2 * f + 1) /= normSin;
96 const MatrixXd& matData,
101 const int nChannels = matGain.rows();
102 const int nSources = matGain.cols();
103 const int nTimes = matData.cols();
105 if (nChannels == 0 || nSources == 0 || nTimes == 0) {
108 const int nAtoms = 2 * params.
iNFreqs;
110 if (matData.rows() != nChannels) {
111 qWarning() <<
"[InvTfMxne::compute] Dimension mismatch: data rows" << matData.rows()
112 <<
"!= gain rows" << nChannels;
128 MatrixXd
Z = MatrixXd::Zero(nSources, nAtoms);
131 VectorXd lipschitz(nSources);
132 for (
int j = 0; j < nSources; ++j) {
133 lipschitz(j) = matGain.col(j).squaredNorm();
136 double phiEnergy = 0.0;
137 for (
int a = 0; a < nAtoms; ++a) {
138 phiEnergy += Phi.row(a).squaredNorm();
140 lipschitz *= phiEnergy;
143 MatrixXd residual = matData;
144 double prevObj = std::numeric_limits<double>::max();
148 MatrixXd
X =
Z * Phi;
149 residual = matData - matGain *
X;
152 double dataFit = residual.squaredNorm();
153 double l21Norm = 0.0;
155 for (
int j = 0; j < nSources; ++j) {
156 l21Norm +=
Z.row(j).norm();
157 l1Norm +=
Z.row(j).lpNorm<1>();
162 if (std::abs(prevObj - objective) / (std::abs(prevObj) + 1e-12) < params.
dTolerance) {
171 MatrixXd GtR = matGain.transpose() * residual;
172 MatrixXd grad = GtR * Phi.transpose();
174 for (
int j = 0; j < nSources; ++j) {
175 if (lipschitz(j) < 1e-12)
continue;
177 double stepSize = 1.0 / lipschitz(j);
180 RowVectorXd zNew =
Z.row(j) + stepSize * grad.row(j);
184 double threshL1 = params.
dAlphaTime * stepSize;
185 for (
int a = 0; a < nAtoms; ++a) {
186 double val = zNew(a);
187 double sign = (val > 0.0) ? 1.0 : -1.0;
188 zNew(a) = sign * std::max(0.0, std::abs(val) - threshL1);
192 double groupNorm = zNew.norm();
194 if (groupNorm > threshL21) {
195 zNew *= (1.0 - threshL21 / groupNorm);
205 MatrixXd
X =
Z * Phi;
208 QVector<int> activeVertices;
209 for (
int j = 0; j < nSources; ++j) {
210 if (
Z.row(j).norm() > 1e-12) {
211 activeVertices.append(j);
217 if (params.
bDebias && !activeVertices.isEmpty()) {
218 MatrixXd Gactive(nChannels, activeVertices.size());
219 for (
int i = 0; i < activeVertices.size(); ++i) {
220 Gactive.col(i) = matGain.col(activeVertices[i]);
223 finalX = Gactive.bdcSvd<ComputeThinU | ComputeThinV>().solve(matData);
224 }
else if (!activeVertices.isEmpty()) {
225 finalX = MatrixXd(activeVertices.size(), nTimes);
226 for (
int i = 0; i < activeVertices.size(); ++i) {
227 finalX.row(i) =
X.row(activeVertices[i]);
230 finalX = MatrixXd::Zero(0, nTimes);
234 VectorXi vertices(activeVertices.size());
235 for (
int i = 0; i < activeVertices.size(); ++i) {
236 vertices(i) = activeVertices[i];
240 static_cast<float>(1.0 / params.
dSFreq));
246 if (!activeVertices.isEmpty()) {
248 for (
int i = 0; i < activeVertices.size(); ++i) {
static Eigen::MatrixXd buildGaborDictionary(int iNSamples, int iNFreqs, double dFMin, double dFMax, double dSFreq)
Build a Gabor dictionary (tight frame) for time-frequency decomposition.