Simplified the feature settings
This commit is contained in:
@@ -58,7 +58,7 @@ class GeneticAlgorithm
|
||||
|
||||
void scoreAndSortPopulation(std::vector<ScoredIndividual>& population);
|
||||
Score getTotalScore(const std::vector<ScoredIndividual>& population) const;
|
||||
typename std::vector<ScoredIndividual>::const_iterator pickRandomRouletteWheel(const std::vector<ScoredIndividual>& population);
|
||||
typename std::vector<ScoredIndividual>::const_iterator pickRandomRouletteWheel(const std::vector<ScoredIndividual>& population, Score totalScore);
|
||||
|
||||
Params _params;
|
||||
};
|
||||
@@ -90,23 +90,22 @@ GeneticAlgorithm<Individual>::simulate(const std::vector<Individual>& initialPop
|
||||
{
|
||||
assert(scoredPopulation.size() == initialPopulation.size());
|
||||
std::cout << "Processing generation " << currentGeneration << "..." << std::endl;
|
||||
std::cout << "Need to create " << childrenCountPerGeneration << " new children" << std::endl;
|
||||
|
||||
// breed
|
||||
const Score populationTotalScore {getTotalScore(scoredPopulation)};
|
||||
std::vector<ScoredIndividual> children;
|
||||
children.reserve(childrenCountPerGeneration);
|
||||
|
||||
while (children.size() < childrenCountPerGeneration)
|
||||
{
|
||||
// Select two random parents using their score as weight
|
||||
const auto itParent1 {pickRandomRouletteWheel(scoredPopulation)};
|
||||
const auto itParent2 {pickRandomRouletteWheel(scoredPopulation)};
|
||||
const auto itParent1 {pickRandomRouletteWheel(scoredPopulation, populationTotalScore)};
|
||||
const auto itParent2 {pickRandomRouletteWheel(scoredPopulation, populationTotalScore)};
|
||||
|
||||
if (itParent1 == itParent2)
|
||||
continue;
|
||||
|
||||
std::cout << "Parent1 = " << std::distance(std::cbegin(scoredPopulation), itParent1) << std::endl;
|
||||
std::cout << "Parent2 = " << std::distance(std::cbegin(scoredPopulation), itParent2) << std::endl;
|
||||
|
||||
ScoredIndividual child {_params.breedFunction(itParent1->individual, itParent2->individual)};
|
||||
|
||||
if (getRealRandom(float {}, float {1}) <= _params.mutationProbability)
|
||||
@@ -155,11 +154,9 @@ GeneticAlgorithm<Individual>::getTotalScore(const std::vector<ScoredIndividual>&
|
||||
|
||||
template<typename Individual>
|
||||
typename std::vector<typename GeneticAlgorithm<Individual>::ScoredIndividual>::const_iterator
|
||||
GeneticAlgorithm<Individual>::pickRandomRouletteWheel(const std::vector<ScoredIndividual>& population)
|
||||
GeneticAlgorithm<Individual>::pickRandomRouletteWheel(const std::vector<ScoredIndividual>& population, Score totalScore)
|
||||
{
|
||||
const Score randomScore {getRealRandom(Score {}, getTotalScore(population))};
|
||||
|
||||
std::cout << "Random = " << randomScore << ", total = " << getTotalScore(population) << std::endl;
|
||||
const Score randomScore {getRealRandom(Score {}, totalScore)};
|
||||
|
||||
Score curScore{};
|
||||
for (auto itScoredIndividual {std::cbegin(population)}; itScoredIndividual != std::cend(population); ++itScoredIndividual )
|
||||
|
||||
@@ -76,11 +76,34 @@ const FeatureSettingsMap featuresSettings
|
||||
{ "lowlevel.hfc.median", {1}},
|
||||
{ "lowlevel.hfc.var", {1}},
|
||||
{ "tonal.hpcp.median", {1}},
|
||||
{ "lowlevel.melbands.mean", {1}},
|
||||
{ "lowlevel.melbands.median", {1}},
|
||||
{ "lowlevel.melbands.var", {1}},
|
||||
{ "lowlevel.melbands_crest.mean", {1}},
|
||||
{ "lowlevel.melbands_crest.median", {1}},
|
||||
{ "lowlevel.melbands_crest.var", {1}},
|
||||
{ "lowlevel.melbands_flatness_db.mean", {1}},
|
||||
{ "lowlevel.melbands_flatness_db.median", {1}},
|
||||
{ "lowlevel.melbands_flatness_db.var", {1}},
|
||||
{ "lowlevel.melbands_kurtosis.mean", {1}},
|
||||
{ "lowlevel.melbands_kurtosis.median", {1}},
|
||||
{ "lowlevel.melbands_kurtosis.var", {1}},
|
||||
{ "lowlevel.melbands_skewness.mean", {1}},
|
||||
{ "lowlevel.melbands_skewness.median", {1}},
|
||||
{ "lowlevel.melbands_skewness.var", {1}},
|
||||
{ "lowlevel.melbands_spread.mean", {1}},
|
||||
{ "lowlevel.melbands_spread.median", {1}},
|
||||
{ "lowlevel.melbands_spread.var", {1}},
|
||||
{ "lowlevel.mfcc.mean", {1}},
|
||||
{ "lowlevel.pitch_salience.mean", {1}},
|
||||
{ "lowlevel.pitch_salience.median", {1}},
|
||||
{ "lowlevel.pitch_salience.var", {1}},
|
||||
{ "lowlevel.silence_rate_30dB.mean", {1}},
|
||||
{ "lowlevel.silence_rate_30dB.median", {1}},
|
||||
{ "lowlevel.silence_rate_30dB.var", {1}},
|
||||
{ "lowlevel.silence_rate_60dB.mean", {1}},
|
||||
{ "lowlevel.silence_rate_60dB.median", {1}},
|
||||
{ "lowlevel.silence_rate_60dB.var", {1}},
|
||||
{ "lowlevel.spectral_centroid.mean", {1}},
|
||||
{ "lowlevel.spectral_centroid.median", {1}},
|
||||
{ "lowlevel.spectral_centroid.var", {1}},
|
||||
@@ -261,10 +284,10 @@ computeTrackScore(Database::Session& session, Database::IdType track1Id, Databas
|
||||
|
||||
static
|
||||
SimilarityScore
|
||||
computeSimilarityScore(Database::Session& session, FeaturesSearcher::TrainSettings trainSettings, const FeatureSettingsMap& featuresSettings)
|
||||
computeSimilarityScore(Database::Session& session, FeaturesSearcher::TrainSettings trainSettings)
|
||||
{
|
||||
std::cout << "Compute score of: ";
|
||||
printFeatureSettingsMap(featuresSettings);
|
||||
printFeatureSettingsMap(trainSettings.featureSettingsMap);
|
||||
std::cout << std::endl;
|
||||
|
||||
FeaturesSearcher searcher {session, trainSettings};
|
||||
@@ -272,7 +295,7 @@ computeSimilarityScore(Database::Session& session, FeaturesSearcher::TrainSettin
|
||||
const std::vector<Database::IdType> trackIds = std::invoke([&]()
|
||||
{
|
||||
auto transaction {session.createSharedTransaction()};
|
||||
return Database::Track::getAllIds(session);
|
||||
return Database::Track::getAllIdsWithFeatures(session);
|
||||
});
|
||||
|
||||
SimilarityScore score {};
|
||||
@@ -297,6 +320,32 @@ computeSimilarityScore(Database::Session& session, FeaturesSearcher::TrainSettin
|
||||
return score;
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
printBadlyClassifiedTracks(Database::Session& session, FeaturesSearcher::TrainSettings trainSettings)
|
||||
{
|
||||
|
||||
FeaturesSearcher searcher {session, trainSettings};
|
||||
|
||||
const std::vector<Database::IdType> trackIds = std::invoke([&]()
|
||||
{
|
||||
auto transaction {session.createSharedTransaction()};
|
||||
return Database::Track::getAllIdsWithFeatures(session);
|
||||
});
|
||||
|
||||
for (Database::IdType trackId : trackIds)
|
||||
{
|
||||
constexpr std::size_t nbSimilarTracks {3};
|
||||
for (Database::IdType similarTrackId : searcher.getSimilarTracks({trackId}, nbSimilarTracks))
|
||||
{
|
||||
SimilarityScore trackScore {computeTrackScore(session, trackId, similarTrackId)};
|
||||
if (trackScore == 0)
|
||||
std::cout << "Badly classified tracks: '" << trackToString(session, trackId) << "'\n\twith track '" << trackToString(session, similarTrackId) << "'" <<std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static
|
||||
FeatureSettingsMap
|
||||
breedFeatureSettingsMap(const FeatureSettingsMap& a, const FeatureSettingsMap& b)
|
||||
@@ -367,7 +416,7 @@ int main(int argc, char *argv[])
|
||||
// Create some random settings (i.e random population)
|
||||
std::vector<FeatureSettingsMap> initialPopulation;
|
||||
|
||||
constexpr std::size_t populationSize {10};
|
||||
constexpr std::size_t populationSize {200};
|
||||
constexpr std::size_t nbFeatures {5};
|
||||
|
||||
for (std::size_t i {}; i < populationSize; ++i)
|
||||
@@ -383,29 +432,31 @@ int main(int argc, char *argv[])
|
||||
initialPopulation.emplace_back(std::move(settings));
|
||||
}
|
||||
|
||||
FeaturesSearcher::TrainSettings trainSettings;
|
||||
trainSettings.iterationCount = 8;
|
||||
trainSettings.sampleCountPerNeuron = 1.5;
|
||||
|
||||
GeneticAlgorithm<FeatureSettingsMap>::Params params;
|
||||
params.nbWorkers = nbWorkers;
|
||||
params.nbGenerations = 5;
|
||||
params.nbGenerations = 1;
|
||||
params.crossoverRatio = 0.78;
|
||||
params.mutationProbability = 0.2;
|
||||
params.breedFunction = breedFeatureSettingsMap;
|
||||
params.mutateFunction = mutateFeatureSettingsMap;
|
||||
params.scoreFunction =
|
||||
[&](const FeatureSettingsMap& settings)
|
||||
[&](const FeatureSettingsMap& featureSettings)
|
||||
{
|
||||
FeaturesSearcher::TrainSettings trainSettings;
|
||||
trainSettings.iterationCount = 8;
|
||||
trainSettings.sampleCountPerNeuron = 1.5;
|
||||
trainSettings.featureSettingsMap = settings;
|
||||
FeaturesSearcher::TrainSettings settings {trainSettings};
|
||||
settings.featureSettingsMap = featureSettings;
|
||||
|
||||
Database::SessionPool::ScopedSession scopedSession {sessionPool};
|
||||
return computeSimilarityScore(scopedSession.get(), trainSettings, settings);
|
||||
return computeSimilarityScore(scopedSession.get(), settings);
|
||||
};
|
||||
|
||||
GeneticAlgorithm<FeatureSettingsMap> geneticAlgorithm {params};
|
||||
|
||||
std::cout << "Parameters:\n"
|
||||
<< "\tnb total settings = "<< featuresSettings.size() << "\n"
|
||||
<< "\tnb generations = " << params.nbGenerations << "\n"
|
||||
<< "\tpopulationSize = " << populationSize << "\n"
|
||||
<< "\tnbFeatures = " << nbFeatures << "\n"
|
||||
@@ -417,6 +468,15 @@ int main(int argc, char *argv[])
|
||||
const FeatureSettingsMap selectedSettings {geneticAlgorithm.simulate(initialPopulation)};
|
||||
std::cout << "Simulation complete! Best result:" << std::endl;
|
||||
printFeatureSettingsMap(selectedSettings);
|
||||
|
||||
// print all badly classified tracks
|
||||
{
|
||||
FeaturesSearcher::TrainSettings settings {trainSettings};
|
||||
settings.featureSettingsMap = selectedSettings;
|
||||
|
||||
Database::SessionPool::ScopedSession scopedSession {sessionPool};
|
||||
printBadlyClassifiedTracks(scopedSession.get(), settings);
|
||||
}
|
||||
}
|
||||
catch (std::exception& e)
|
||||
{
|
||||
|
||||
@@ -11,7 +11,6 @@ lms_similarity_parameters_SOURCES = \
|
||||
$(top_srcdir)/src/database/ScanSettings.cpp \
|
||||
$(top_srcdir)/src/database/Session.cpp \
|
||||
$(top_srcdir)/src/database/SessionPool.cpp \
|
||||
$(top_srcdir)/src/database/SimilaritySettings.cpp \
|
||||
$(top_srcdir)/src/database/SqlQuery.cpp \
|
||||
$(top_srcdir)/src/database/Track.cpp \
|
||||
$(top_srcdir)/src/database/User.cpp \
|
||||
|
||||
@@ -42,54 +42,6 @@ int main(int argc, char *argv[])
|
||||
// log to stdout
|
||||
ServiceProvider<Logger>::create<StreamLogger>(std::cout);
|
||||
|
||||
const FeatureSettingsMap featuresSettings
|
||||
{
|
||||
/* { "lowlevel.average_loudness", 1 },
|
||||
{ "lowlevel.dynamic_complexity", 1 },
|
||||
{ "lowlevel.spectral_contrast_coeffs.median", {1} },
|
||||
{ "lowlevel.erbbands.median", {1} },
|
||||
{ "tonal.hpcp.median", {1} },
|
||||
{ "lowlevel.melbands.median", {1} },
|
||||
{ "lowlevel.barkbands.median", {1} },
|
||||
{ "lowlevel.mfcc.mean", {1} },
|
||||
{ "lowlevel.gfcc.mean", {1} },
|
||||
*/
|
||||
{ "lowlevel.spectral_kurtosis.median", {1}},
|
||||
{ "lowlevel.spectral_kurtosis.mean", {1}},
|
||||
{ "lowlevel.spectral_complexity.var", {1}},
|
||||
{ "lowlevel.barkbands.median", {1}},
|
||||
{ "lowlevel.barkbands_kurtosis.mean", {1}},
|
||||
/*
|
||||
{"lowlevel.spectral_centroid.dvar2", {1} },
|
||||
{"lowlevel.barkbands.median", {1} },
|
||||
{ "lowlevel.barkbands.dvar", {1} },
|
||||
{ "lowlevel.spectral_complexity.min", {1} },
|
||||
{ "lowlevel.pitch_salience.dmean2", {1} },
|
||||
{ "lowlevel.spectral_contrast_valleys.dmean", {1} },
|
||||
{ "lowlevel.pitch_salience.max", {1} },
|
||||
{ "lowlevel.barkbands.mean", {1} },
|
||||
{ "lowlevel.spectral_complexity.mean", {1} },
|
||||
{ "lowlevel.dissonance.dvar", {1} },
|
||||
*/
|
||||
/*
|
||||
{ "lowlevel.spectral_energy.dvar", {1} },
|
||||
{ "lowlevel.barkbands.min", {1} },
|
||||
{ "lowlevel.spectral_centroid.median", {1} },
|
||||
{"lowlevel.barkbands_kurtosis.median", {1} },
|
||||
{"lowlevel.spectral_energy.median", {1} },
|
||||
{"lowlevel.barkbands.max", {1} },
|
||||
{"lowlevel.barkbands_spread.var", {1} },
|
||||
{"lowlevel.spectral_decrease.var", {1} },
|
||||
{"lowlevel.spectral_contrast_valleys.dmean", {1} },
|
||||
{"lowlevel.barkbands_crest.mean", {1} },
|
||||
{"lowlevel.spectral_entropy.var", {1} },
|
||||
{"lowlevel.barkbands_crest.max", {1} },
|
||||
{"lowlevel.hfc.dvar", {1} },
|
||||
{"lowlevel.barkbands_skewness.dvar2", {1} },
|
||||
{"lowlevel.spectral_centroid.max", {1} },
|
||||
*/
|
||||
};
|
||||
|
||||
std::filesystem::path configFilePath {"/etc/lms.conf"};
|
||||
if (argc >= 2)
|
||||
configFilePath = std::string(argv[1], 0, 256);
|
||||
@@ -102,17 +54,17 @@ int main(int argc, char *argv[])
|
||||
std::cout << "Classifying tracks..." << std::endl;
|
||||
// may be long...
|
||||
struct FeaturesSearcher::TrainSettings trainSettings;
|
||||
trainSettings.featureSettingsMap = featuresSettings;
|
||||
trainSettings.featureSettingsMap = FeaturesSearcher::getDefaultTrainFeatureSettings();
|
||||
FeaturesSearcher searcher {session, trainSettings};
|
||||
std::cout << "Classifying tracks DONE" << std::endl;
|
||||
|
||||
const std::vector<Database::IdType> trackIds = std::invoke([&]()
|
||||
{
|
||||
auto transaction {session.createSharedTransaction()};
|
||||
return Database::Track::getAllIds(session);
|
||||
return Database::Track::getAllIdsWithFeatures(session);
|
||||
});
|
||||
|
||||
std::cout << "*** Tracks ***" << std::endl;
|
||||
std::cout << "*** Tracks (" << trackIds.size() << ") ***" << std::endl;
|
||||
for (Database::IdType trackId : trackIds)
|
||||
{
|
||||
auto trackToString = [&](Database::IdType trackId)
|
||||
|
||||
@@ -10,7 +10,6 @@ lms_similarity_SOURCES = \
|
||||
$(top_srcdir)/src/database/Release.cpp \
|
||||
$(top_srcdir)/src/database/ScanSettings.cpp \
|
||||
$(top_srcdir)/src/database/Session.cpp \
|
||||
$(top_srcdir)/src/database/SimilaritySettings.cpp \
|
||||
$(top_srcdir)/src/database/SqlQuery.cpp \
|
||||
$(top_srcdir)/src/database/Track.cpp \
|
||||
$(top_srcdir)/src/database/User.cpp \
|
||||
|
||||
Reference in New Issue
Block a user