Added some more tools
This commit is contained in:
@@ -1,7 +1,7 @@
|
|||||||
|
|
||||||
add_library(lmsrecommendation SHARED
|
add_library(lmsrecommendation SHARED
|
||||||
impl/Engine.cpp
|
impl/Engine.cpp
|
||||||
impl/ProviderCreator.cpp
|
impl/ClassifierCreator.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
target_include_directories(lmsrecommendation INTERFACE
|
target_include_directories(lmsrecommendation INTERFACE
|
||||||
|
|||||||
+5
-5
@@ -17,19 +17,19 @@
|
|||||||
* along with LMS. If not, see <http://www.gnu.org/licenses/>.
|
* along with LMS. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "recommendation/ClustersRecommendationProviderCreator.hpp"
|
#include "recommendation/ClustersClassifierCreator.hpp"
|
||||||
#include "recommendation/FeaturesRecommendationProviderCreator.hpp"
|
#include "recommendation/FeaturesClassifierCreator.hpp"
|
||||||
#include "recommendation/Provider.hpp"
|
#include "recommendation/Classifier.hpp"
|
||||||
|
|
||||||
namespace Recommendation
|
namespace Recommendation
|
||||||
{
|
{
|
||||||
|
|
||||||
std::unique_ptr<Provider> createClustersRecommendationProvider()
|
std::unique_ptr<Classifier> createClustersClassifier()
|
||||||
{
|
{
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<Provider> createFeaturesRecommendationProvider(Scanner::IMediaScanner&)
|
std::unique_ptr<Classifier> createFeaturesClassifier()
|
||||||
{
|
{
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
@@ -34,15 +34,15 @@ createEngine()
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
Engine::clearProviders()
|
Engine::clearClassifiers()
|
||||||
{
|
{
|
||||||
_providers.clear();
|
_classifiers.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
Engine::addProvider(std::unique_ptr<Provider> provider, unsigned priority)
|
Engine::addClassifier(std::unique_ptr<Classifier> classifier, unsigned priority)
|
||||||
{
|
{
|
||||||
_providers.emplace(priority, std::move(provider));
|
_classifiers.emplace(priority, std::move(classifier));
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<Database::IdType>
|
std::vector<Database::IdType>
|
||||||
|
|||||||
@@ -22,7 +22,7 @@
|
|||||||
#include <map>
|
#include <map>
|
||||||
|
|
||||||
#include "recommendation/IEngine.hpp"
|
#include "recommendation/IEngine.hpp"
|
||||||
#include "recommendation/Provider.hpp"
|
#include "recommendation/Classifier.hpp"
|
||||||
|
|
||||||
namespace Database
|
namespace Database
|
||||||
{
|
{
|
||||||
@@ -34,9 +34,6 @@ namespace Recommendation
|
|||||||
class Engine : public IEngine
|
class Engine : public IEngine
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
void clearProviders() override;
|
|
||||||
void addProvider(std::unique_ptr<Provider> provider, unsigned priority) override;
|
|
||||||
|
|
||||||
// Closest results first
|
// Closest results first
|
||||||
std::vector<Database::IdType> getSimilarTracksFromTrackList(Database::Session& session, Database::IdType tracklistId, std::size_t maxCount) override;
|
std::vector<Database::IdType> getSimilarTracksFromTrackList(Database::Session& session, Database::IdType tracklistId, std::size_t maxCount) override;
|
||||||
std::vector<Database::IdType> getSimilarTracks(Database::Session& session, const std::unordered_set<Database::IdType>& tracksId, std::size_t maxCount) override;
|
std::vector<Database::IdType> getSimilarTracks(Database::Session& session, const std::unordered_set<Database::IdType>& tracksId, std::size_t maxCount) override;
|
||||||
@@ -44,8 +41,10 @@ namespace Recommendation
|
|||||||
std::vector<Database::IdType> getSimilarArtists(Database::Session& session, Database::IdType artistId, std::size_t maxCount) override;
|
std::vector<Database::IdType> getSimilarArtists(Database::Session& session, Database::IdType artistId, std::size_t maxCount) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
void clearClassifiers();
|
||||||
|
void addClassifier(std::unique_ptr<Classifier> classifier, unsigned priority);
|
||||||
|
|
||||||
std::map<unsigned, std::unique_ptr<Provider>> _providers;
|
std::map<unsigned, std::unique_ptr<Classifier>> _classifiers;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // ns Recommendation
|
} // ns Recommendation
|
||||||
|
|||||||
+4
-2
@@ -32,10 +32,12 @@ namespace Database
|
|||||||
namespace Recommendation
|
namespace Recommendation
|
||||||
{
|
{
|
||||||
|
|
||||||
class Provider
|
class Classifier
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
virtual ~Provider() = default;
|
virtual ~Classifier() = default;
|
||||||
|
|
||||||
|
virtual void classify() = 0;
|
||||||
|
|
||||||
virtual bool isTrackClassified(Database::IdType trackId) const = 0;
|
virtual bool isTrackClassified(Database::IdType trackId) const = 0;
|
||||||
virtual bool isReleaseClassified(Database::IdType releaseId) const = 0;
|
virtual bool isReleaseClassified(Database::IdType releaseId) const = 0;
|
||||||
+2
-2
@@ -28,8 +28,8 @@ namespace Database
|
|||||||
|
|
||||||
namespace Recommendation
|
namespace Recommendation
|
||||||
{
|
{
|
||||||
class Provider;
|
class Classifier;
|
||||||
|
|
||||||
std::unique_ptr<Provider> createClustersRecommendationProvider();
|
std::unique_ptr<Classifier> createClustersClassifier();
|
||||||
}
|
}
|
||||||
|
|
||||||
+2
-7
@@ -26,15 +26,10 @@ namespace Database
|
|||||||
class Session;
|
class Session;
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace Scanner
|
|
||||||
{
|
|
||||||
class IMediaScanner;
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace Recommendation
|
namespace Recommendation
|
||||||
{
|
{
|
||||||
class Provider;
|
class Classifier;
|
||||||
|
|
||||||
std::unique_ptr<Provider> createFeaturesRecommendationProvider(Scanner::IMediaScanner& scanner);
|
std::unique_ptr<Classifier> createFeaturesClassifier();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -23,7 +23,7 @@
|
|||||||
#include <unordered_set>
|
#include <unordered_set>
|
||||||
|
|
||||||
#include "database/Types.hpp"
|
#include "database/Types.hpp"
|
||||||
#include "Provider.hpp"
|
#include "Classifier.hpp"
|
||||||
|
|
||||||
namespace Database
|
namespace Database
|
||||||
{
|
{
|
||||||
@@ -32,15 +32,12 @@ namespace Database
|
|||||||
|
|
||||||
namespace Recommendation
|
namespace Recommendation
|
||||||
{
|
{
|
||||||
class Provider;
|
class Classifier;
|
||||||
class IEngine
|
class IEngine
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
virtual ~IEngine() = default;
|
virtual ~IEngine() = default;
|
||||||
|
|
||||||
virtual void clearProviders() = 0;
|
|
||||||
virtual void addProvider(std::unique_ptr<Provider> provider, unsigned priority) = 0;
|
|
||||||
|
|
||||||
// Closest results first
|
// Closest results first
|
||||||
virtual std::vector<Database::IdType> getSimilarTracksFromTrackList(Database::Session& session, Database::IdType tracklistId, std::size_t maxCount) = 0;
|
virtual std::vector<Database::IdType> getSimilarTracksFromTrackList(Database::Session& session, Database::IdType tracklistId, std::size_t maxCount) = 0;
|
||||||
virtual std::vector<Database::IdType> getSimilarTracks(Database::Session& session, const std::unordered_set<Database::IdType>& tracksId, std::size_t maxCount) = 0;
|
virtual std::vector<Database::IdType> getSimilarTracks(Database::Session& session, const std::unordered_set<Database::IdType>& tracksId, std::size_t maxCount) = 0;
|
||||||
|
|||||||
+1
-5
@@ -29,9 +29,7 @@
|
|||||||
#include "cover/ICoverArtGrabber.hpp"
|
#include "cover/ICoverArtGrabber.hpp"
|
||||||
#include "database/Db.hpp"
|
#include "database/Db.hpp"
|
||||||
#include "scanner/IMediaScanner.hpp"
|
#include "scanner/IMediaScanner.hpp"
|
||||||
#include "recommendation/FeaturesRecommendationProviderCreator.hpp"
|
|
||||||
#include "recommendation/IEngine.hpp"
|
#include "recommendation/IEngine.hpp"
|
||||||
#include "recommendation/ClustersRecommendationProviderCreator.hpp"
|
|
||||||
#include "subsonic/SubsonicResource.hpp"
|
#include "subsonic/SubsonicResource.hpp"
|
||||||
#include "ui/LmsApplication.hpp"
|
#include "ui/LmsApplication.hpp"
|
||||||
#include "utils/IConfig.hpp"
|
#include "utils/IConfig.hpp"
|
||||||
@@ -145,9 +143,7 @@ int main(int argc, char* argv[])
|
|||||||
ServiceProvider<Auth::IPasswordService>::assign(Auth::createPasswordService(ServiceProvider<IConfig>::get()->getULong("login-throttler-max-entriees", 10000)));
|
ServiceProvider<Auth::IPasswordService>::assign(Auth::createPasswordService(ServiceProvider<IConfig>::get()->getULong("login-throttler-max-entriees", 10000)));
|
||||||
Scanner::IMediaScanner& mediaScanner {ServiceProvider<Scanner::IMediaScanner>::assign(Scanner::createMediaScanner(database))};
|
Scanner::IMediaScanner& mediaScanner {ServiceProvider<Scanner::IMediaScanner>::assign(Scanner::createMediaScanner(database))};
|
||||||
|
|
||||||
Recommendation::IEngine& recommendationEngine {ServiceProvider<Recommendation::IEngine>::assign(Recommendation::createEngine())};
|
ServiceProvider<Recommendation::IEngine>::assign(Recommendation::createEngine());
|
||||||
recommendationEngine.addProvider(Recommendation::createFeaturesRecommendationProvider(mediaScanner), 0);
|
|
||||||
recommendationEngine.addProvider(Recommendation::createClustersRecommendationProvider(), 1);
|
|
||||||
|
|
||||||
CoverArt::IGrabber& coverArtGrabber {ServiceProvider<CoverArt::IGrabber>::assign(CoverArt::createGrabber(argv[0]))};
|
CoverArt::IGrabber& coverArtGrabber {ServiceProvider<CoverArt::IGrabber>::assign(CoverArt::createGrabber(argv[0]))};
|
||||||
coverArtGrabber.setDefaultCover(server.appRoot() + "/images/unknown-cover.jpg");
|
coverArtGrabber.setDefaultCover(server.appRoot() + "/images/unknown-cover.jpg");
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
|
|
||||||
add_subdirectory(metadata)
|
add_subdirectory(metadata)
|
||||||
|
add_subdirectory(recommendation-features)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,10 @@
|
|||||||
|
|
||||||
|
add_executable(lms-recommendation-features
|
||||||
|
LmsRecommendationFeatures.cpp
|
||||||
|
)
|
||||||
|
|
||||||
|
target_link_libraries(lms-recommendation-features PRIVATE
|
||||||
|
lmsdatabase
|
||||||
|
lmsrecommendation
|
||||||
|
)
|
||||||
|
|
||||||
+11
-12
@@ -28,17 +28,16 @@
|
|||||||
#include "database/Release.hpp"
|
#include "database/Release.hpp"
|
||||||
#include "database/Session.hpp"
|
#include "database/Session.hpp"
|
||||||
#include "database/Track.hpp"
|
#include "database/Track.hpp"
|
||||||
#include "utils/Config.hpp"
|
#include "utils/IConfig.hpp"
|
||||||
#include "utils/Service.hpp"
|
#include "utils/Service.hpp"
|
||||||
#include "utils/StreamLogger.hpp"
|
#include "utils/StreamLogger.hpp"
|
||||||
#include "similarity/features/SimilarityFeaturesSearcher.hpp"
|
#include "recommendation/IEngine.hpp"
|
||||||
|
#include "recommendation/FeaturesClassifierCreator.hpp"
|
||||||
|
|
||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
using namespace Similarity;
|
|
||||||
|
|
||||||
// log to stdout
|
// log to stdout
|
||||||
ServiceProvider<Logger>::create<StreamLogger>(std::cout);
|
ServiceProvider<Logger>::create<StreamLogger>(std::cout);
|
||||||
|
|
||||||
@@ -46,16 +45,16 @@ int main(int argc, char *argv[])
|
|||||||
if (argc >= 2)
|
if (argc >= 2)
|
||||||
configFilePath = std::string(argv[1], 0, 256);
|
configFilePath = std::string(argv[1], 0, 256);
|
||||||
|
|
||||||
ServiceProvider<Config>::create(configFilePath);
|
ServiceProvider<IConfig>::assign(createConfig(configFilePath));
|
||||||
|
|
||||||
Database::Db db {ServiceProvider<Config>::get()->getPath("working-dir") / "lms.db"};
|
Database::Db db {ServiceProvider<IConfig>::get()->getPath("working-dir") / "lms.db"};
|
||||||
Database::Session session {db};
|
Database::Session session {db};
|
||||||
|
|
||||||
|
auto classifier {Recommendation::createFeaturesClassifier()};
|
||||||
|
|
||||||
std::cout << "Classifying tracks..." << std::endl;
|
std::cout << "Classifying tracks..." << std::endl;
|
||||||
// may be long...
|
// may be long...
|
||||||
struct FeaturesSearcher::TrainSettings trainSettings;
|
classifier->classify();
|
||||||
trainSettings.featureSettingsMap = FeaturesSearcher::getDefaultTrainFeatureSettings();
|
|
||||||
FeaturesSearcher searcher {session, trainSettings};
|
|
||||||
std::cout << "Classifying tracks DONE" << std::endl;
|
std::cout << "Classifying tracks DONE" << std::endl;
|
||||||
|
|
||||||
const std::vector<Database::IdType> trackIds = std::invoke([&]()
|
const std::vector<Database::IdType> trackIds = std::invoke([&]()
|
||||||
@@ -85,7 +84,7 @@ int main(int argc, char *argv[])
|
|||||||
};
|
};
|
||||||
|
|
||||||
std::cout << "Processing track '" << trackToString(trackId) << std::endl;
|
std::cout << "Processing track '" << trackToString(trackId) << std::endl;
|
||||||
for (Database::IdType similarTrackId : searcher.getSimilarTracks({trackId}, 3))
|
for (Database::IdType similarTrackId : classifier->getSimilarTracks(session, {trackId}, 3))
|
||||||
std::cout << "\t- Similar track '" << trackToString(similarTrackId) << std::endl;
|
std::cout << "\t- Similar track '" << trackToString(similarTrackId) << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -107,7 +106,7 @@ int main(int argc, char *argv[])
|
|||||||
};
|
};
|
||||||
|
|
||||||
std::cout << "Processing release '" << releaseToString(releaseId) << "'" << std::endl;
|
std::cout << "Processing release '" << releaseToString(releaseId) << "'" << std::endl;
|
||||||
for (Database::IdType similarReleaseId : searcher.getSimilarReleases({releaseId}, 3))
|
for (Database::IdType similarReleaseId : classifier->getSimilarReleases({releaseId}, 3))
|
||||||
std::cout << "\t- Similar release '" << releaseToString(similarReleaseId) << "'" << std::endl;
|
std::cout << "\t- Similar release '" << releaseToString(similarReleaseId) << "'" << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -129,7 +128,7 @@ int main(int argc, char *argv[])
|
|||||||
};
|
};
|
||||||
|
|
||||||
std::cout << "Processing artist '" << artistToString(artistId) << "'" << std::endl;
|
std::cout << "Processing artist '" << artistToString(artistId) << "'" << std::endl;
|
||||||
for (Database::IdType similarArtistId : searcher.getSimilarArtists({artistId}, 3))
|
for (Database::IdType similarArtistId : classifier->getSimilarArtists({artistId}, 3))
|
||||||
std::cout << "\t- Similar artist '" << artistToString(similarArtistId) << "'" << std::endl;
|
std::cout << "\t- Similar artist '" << artistToString(similarArtistId) << "'" << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1,29 +0,0 @@
|
|||||||
noinst_PROGRAMS = lms-similarity-parameters
|
|
||||||
|
|
||||||
lms_similarity_parameters_SOURCES = \
|
|
||||||
$(srcdir)/LmsSimilarityParameters.cpp \
|
|
||||||
$(top_srcdir)/src/database/Artist.cpp \
|
|
||||||
$(top_srcdir)/src/database/Cluster.cpp \
|
|
||||||
$(top_srcdir)/src/database/Db.cpp \
|
|
||||||
$(top_srcdir)/src/database/TrackFeatures.cpp \
|
|
||||||
$(top_srcdir)/src/database/TrackList.cpp \
|
|
||||||
$(top_srcdir)/src/database/Release.cpp \
|
|
||||||
$(top_srcdir)/src/database/ScanSettings.cpp \
|
|
||||||
$(top_srcdir)/src/database/Session.cpp \
|
|
||||||
$(top_srcdir)/src/database/SessionPool.cpp \
|
|
||||||
$(top_srcdir)/src/database/SqlQuery.cpp \
|
|
||||||
$(top_srcdir)/src/database/Track.cpp \
|
|
||||||
$(top_srcdir)/src/database/User.cpp \
|
|
||||||
$(top_srcdir)/src/similarity/features/som/DataNormalizer.cpp \
|
|
||||||
$(top_srcdir)/src/similarity/features/som/Network.cpp \
|
|
||||||
$(top_srcdir)/src/similarity/features/SimilarityFeaturesCache.cpp \
|
|
||||||
$(top_srcdir)/src/similarity/features/SimilarityFeaturesSearcher.cpp \
|
|
||||||
$(top_srcdir)/src/similarity/features/SimilarityFeaturesDefs.cpp \
|
|
||||||
$(top_srcdir)/src/utils/Config.cpp \
|
|
||||||
$(top_srcdir)/src/utils/Logger.cpp \
|
|
||||||
$(top_srcdir)/src/utils/Random.cpp \
|
|
||||||
$(top_srcdir)/src/utils/StreamLogger.cpp \
|
|
||||||
$(top_srcdir)/src/utils/String.cpp
|
|
||||||
|
|
||||||
lms_similarity_parameters_CXXFLAGS=-std=c++17 -I$(top_srcdir)/src -D_REENTRANT
|
|
||||||
|
|
||||||
@@ -1,27 +0,0 @@
|
|||||||
noinst_PROGRAMS = lms-similarity
|
|
||||||
|
|
||||||
lms_similarity_SOURCES = \
|
|
||||||
$(srcdir)/LmsSimilarity.cpp \
|
|
||||||
$(top_srcdir)/src/database/Artist.cpp \
|
|
||||||
$(top_srcdir)/src/database/Cluster.cpp \
|
|
||||||
$(top_srcdir)/src/database/Db.cpp \
|
|
||||||
$(top_srcdir)/src/database/TrackFeatures.cpp \
|
|
||||||
$(top_srcdir)/src/database/TrackList.cpp \
|
|
||||||
$(top_srcdir)/src/database/Release.cpp \
|
|
||||||
$(top_srcdir)/src/database/ScanSettings.cpp \
|
|
||||||
$(top_srcdir)/src/database/Session.cpp \
|
|
||||||
$(top_srcdir)/src/database/SqlQuery.cpp \
|
|
||||||
$(top_srcdir)/src/database/Track.cpp \
|
|
||||||
$(top_srcdir)/src/database/User.cpp \
|
|
||||||
$(top_srcdir)/src/similarity/features/som/DataNormalizer.cpp \
|
|
||||||
$(top_srcdir)/src/similarity/features/som/Network.cpp \
|
|
||||||
$(top_srcdir)/src/similarity/features/SimilarityFeaturesCache.cpp \
|
|
||||||
$(top_srcdir)/src/similarity/features/SimilarityFeaturesSearcher.cpp \
|
|
||||||
$(top_srcdir)/src/similarity/features/SimilarityFeaturesDefs.cpp \
|
|
||||||
$(top_srcdir)/src/utils/Config.cpp \
|
|
||||||
$(top_srcdir)/src/utils/Logger.cpp \
|
|
||||||
$(top_srcdir)/src/utils/StreamLogger.cpp \
|
|
||||||
$(top_srcdir)/src/utils/String.cpp
|
|
||||||
|
|
||||||
lms_similarity_CXXFLAGS=-std=c++17 -I$(top_srcdir)/src -D_REENTRANT
|
|
||||||
|
|
||||||
Reference in New Issue
Block a user