├── .gitignore
├── .travis.yml
├── CODE_OF_CONDUCT.md
├── CONTRIBUTING.md
├── LICENSE.txt
├── README.md
├── codecov.yml
├── pom.xml
├── rival-core
├── pom.xml
└── src
│ ├── main
│ └── java
│ │ └── net
│ │ └── recommenders
│ │ └── rival
│ │ └── core
│ │ ├── AbstractParser.java
│ │ ├── DataModel.java
│ │ ├── DataModelFactory.java
│ │ ├── DataModelIF.java
│ │ ├── DataModelUtils.java
│ │ ├── Parser.java
│ │ ├── ParserWithIdMapping.java
│ │ ├── SimpleParser.java
│ │ ├── TemporalDataModel.java
│ │ ├── TemporalDataModelIF.java
│ │ ├── UIPParser.java
│ │ ├── ext
│ │ ├── MahoutDataModel.java
│ │ └── RankSysDataModel.java
│ │ └── package-info.java
│ └── test
│ └── java
│ └── net
│ └── recommenders
│ └── rival
│ └── core
│ └── DataModelTest.java
├── rival-evaluate
├── pom.xml
├── run.sh
└── src
│ ├── main
│ ├── java
│ │ └── net
│ │ │ └── recommenders
│ │ │ └── rival
│ │ │ └── evaluation
│ │ │ ├── Pair.java
│ │ │ ├── metric
│ │ │ ├── AbstractMetric.java
│ │ │ ├── EvaluationMetric.java
│ │ │ ├── EvaluationMetricRunner.java
│ │ │ ├── MultipleEvaluationMetricRunner.java
│ │ │ ├── error
│ │ │ │ ├── AbstractErrorMetric.java
│ │ │ │ ├── MAE.java
│ │ │ │ ├── RMSE.java
│ │ │ │ └── package-info.java
│ │ │ ├── package-info.java
│ │ │ └── ranking
│ │ │ │ ├── AbstractRankingMetric.java
│ │ │ │ ├── MAP.java
│ │ │ │ ├── NDCG.java
│ │ │ │ ├── PopularityStratifiedRecall.java
│ │ │ │ ├── Precision.java
│ │ │ │ ├── Recall.java
│ │ │ │ └── package-info.java
│ │ │ ├── package-info.java
│ │ │ ├── parser
│ │ │ ├── TrecEvalParser.java
│ │ │ └── package-info.java
│ │ │ ├── statistics
│ │ │ ├── ConfidenceInterval.java
│ │ │ ├── EffectSize.java
│ │ │ ├── StandardError.java
│ │ │ ├── StatisticalSignificance.java
│ │ │ ├── StatisticsRunner.java
│ │ │ └── package-info.java
│ │ │ └── strategy
│ │ │ ├── AbstractStrategy.java
│ │ │ ├── AllItems.java
│ │ │ ├── EvaluationStrategy.java
│ │ │ ├── EvaluationStrategyPerItem.java
│ │ │ ├── MultipleStrategyRunner.java
│ │ │ ├── MultipleStrategyRunnerInfile.java
│ │ │ ├── RelPlusN.java
│ │ │ ├── StrategyIO.java
│ │ │ ├── StrategyRunner.java
│ │ │ ├── StrategyRunnerInfile.java
│ │ │ ├── TestItems.java
│ │ │ ├── TrainItems.java
│ │ │ ├── UserTest.java
│ │ │ └── package-info.java
│ └── resources
│ │ ├── allitems.strategy.properties
│ │ ├── metric.properties
│ │ ├── relplusn.strategy.properties
│ │ ├── statistics.properties
│ │ ├── strategy.properties
│ │ ├── testitems.strategy.properties
│ │ ├── trainitems.strategy.properties
│ │ └── usertest.strategy.properties
│ └── test
│ └── java
│ └── net
│ └── recommenders
│ └── rival
│ └── evaluation
│ ├── metric
│ ├── MAETest.java
│ ├── MAPTest.java
│ ├── NDCGTest.java
│ ├── PopularityStratifiedRecallTest.java
│ ├── PrecisionTest.java
│ ├── RMSETest.java
│ └── RecallTest.java
│ └── statistics
│ └── StatisticsTest.java
├── rival-examples
├── pom.xml
└── src
│ └── main
│ └── java
│ └── net
│ └── recommenders
│ └── rival
│ └── examples
│ ├── CompletePipelineInMemory.java
│ ├── DataDownloader.java
│ ├── mdp
│ ├── CrossValidationRecSysEvaluator.java
│ ├── EvaluationMetrics.java
│ ├── MahoutItemBasedCFRecSysEvaluator.java
│ └── Main.java
│ ├── movielens100k
│ ├── CrossValidatedMahoutKNNRecommenderEvaluator.java
│ ├── IterativeCrossValidatedMahoutKNNRecommenderEvaluator.java
│ ├── RandomSplitMahoutKNNRecommenderEvaluator.java
│ ├── TemporalSplitMahoutKNNRecommenderEvaluator.java
│ └── package-info.java
│ ├── movietweetings
│ ├── RandomMahoutIBRecommenderEvaluator.java
│ └── package-info.java
│ └── package-info.java
├── rival-package
├── pom.xml
└── src
│ └── text
│ ├── APL.txt
│ └── LICENSE.txt
├── rival-recommend
├── pom.xml
└── src
│ ├── main
│ ├── java
│ │ └── net
│ │ │ └── recommenders
│ │ │ └── rival
│ │ │ └── recommend
│ │ │ └── frameworks
│ │ │ ├── AbstractRunner.java
│ │ │ ├── MultipleRecommendationRunner.java
│ │ │ ├── RecommendationRunner.java
│ │ │ ├── RecommenderIO.java
│ │ │ ├── exceptions
│ │ │ ├── RecommenderException.java
│ │ │ └── package-info.java
│ │ │ ├── lenskit
│ │ │ ├── EventDAOWrapper.java
│ │ │ ├── LenskitRecommenderRunner.java
│ │ │ └── package-info.java
│ │ │ ├── librec
│ │ │ ├── DataDAOWrapper.java
│ │ │ └── LibrecRecommenderRunner.java
│ │ │ ├── mahout
│ │ │ ├── DataModelWrapper.java
│ │ │ ├── GenericRecommenderBuilder.java
│ │ │ ├── MahoutRecommenderRunner.java
│ │ │ ├── PopularityBasedRecommender.java
│ │ │ └── package-info.java
│ │ │ ├── package-info.java
│ │ │ └── ranksys
│ │ │ ├── ItemIndexWrapper.java
│ │ │ ├── PreferenceDataWrapper.java
│ │ │ ├── RanksysRecommenderRunner.java
│ │ │ ├── UserIndexWrapper.java
│ │ │ └── package-info.java
│ └── resources
│ │ ├── lenskit.item-based.properties
│ │ ├── lenskit.properties
│ │ ├── lenskit.svd.properties
│ │ ├── lenskit.user-based.properties
│ │ ├── librec.svd.properties
│ │ ├── mahout.item-based.properties
│ │ ├── mahout.properties
│ │ ├── mahout.svd.properties
│ │ ├── mahout.user-based.properties
│ │ ├── ranksys.properties
│ │ ├── ranksys.svd.properties
│ │ └── ranksys.user-based.properties
│ └── test
│ └── java
│ └── net
│ └── recommenders
│ └── rival
│ └── recommend
│ └── frameworks
│ └── mahout
│ └── GenericRecommenderBuilderTest.java
├── rival-split
├── pom.xml
├── run.sh
├── scripts
│ ├── crossvalidation_splitter.sh
│ ├── random_splitter.sh
│ └── temporal_splitter.sh
└── src
│ ├── main
│ ├── java
│ │ └── net
│ │ │ └── recommenders
│ │ │ └── rival
│ │ │ └── split
│ │ │ ├── parser
│ │ │ ├── AbstractLastfmCelmaParser.java
│ │ │ ├── LastfmCelma1KParser.java
│ │ │ ├── LastfmCelma360KParser.java
│ │ │ ├── MovielensParser.java
│ │ │ ├── ParserRunner.java
│ │ │ └── package-info.java
│ │ │ └── splitter
│ │ │ ├── CrossValidationSplitter.java
│ │ │ ├── IterativeCrossValidationSplitter.java
│ │ │ ├── IterativeLeaveOneOutSplitter.java
│ │ │ ├── RandomSplitter.java
│ │ │ ├── Split.java
│ │ │ ├── Splitter.java
│ │ │ ├── SplitterRunner.java
│ │ │ ├── TemporalSplitter.java
│ │ │ ├── ValidationSplitter.java
│ │ │ └── package-info.java
│ └── resources
│ │ ├── lastfmcelma360k.cv.global.artist.splitter.properties
│ │ ├── lastfmcelma360k.rnd.global.artist.splitter.properties
│ │ ├── movielens100k.cv.global.splitter.properties
│ │ ├── movielens100k.cv.peruser.splitter.properties
│ │ ├── movielens100k.rnd.global.splitter.properties
│ │ └── movielens100k.rnd.peruser.splitter.properties
│ └── test
│ └── java
│ └── net
│ └── recommenders
│ └── rival
│ └── split
│ └── splitter
│ └── SplitTest.java
└── src
├── assemble
└── source-package.xml
├── main
└── resources
│ └── rival_checks.xml
└── site
├── markdown
├── index.md
└── releases
│ ├── index.md.vm
│ ├── relnotes.vm
│ └── rival-0.1.md
├── resources
└── logo.png
└── site.xml
/.gitignore:
--------------------------------------------------------------------------------
1 | target/
2 | *.iml
3 | nbactions.xml
4 | .idea/
5 | nb-configuration.xml
6 | rival-examples/data/
7 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: java
2 | jdk:
3 | - oraclejdk8
4 | sudo: false
5 | notifications:
6 | slack:
7 | secure: IdTbYOGWdDQsVowiseeb09qk/T0zdadBSZeofi4L015xzFfuMs6tiOECrEjNr+2Pa7vbZlnCQRgWdFKBRL3urXf7+LO7RI9j57SsJ8sI6LaqbMJHcvs8jxm4Lp1HT4QEzHwrxPJxJtmAv/w6lJ95hgTejcQktgqfMsbGSlfkfaE=
8 | script: "mvn cobertura:cobertura"
9 | after_success:
10 | - bash <(curl -s https://codecov.io/bash)
11 |
--------------------------------------------------------------------------------
/CODE_OF_CONDUCT.md:
--------------------------------------------------------------------------------
1 | # Contributor Covenant Code of Conduct
2 |
3 | ## Our Pledge
4 |
5 | In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation.
6 |
7 | ## Our Standards
8 |
9 | Examples of behavior that contributes to creating a positive environment include:
10 |
11 | * Using welcoming and inclusive language
12 | * Being respectful of differing viewpoints and experiences
13 | * Gracefully accepting constructive criticism
14 | * Focusing on what is best for the community
15 | * Showing empathy towards other community members
16 |
17 | Examples of unacceptable behavior by participants include:
18 |
19 | * The use of sexualized language or imagery and unwelcome sexual attention or advances
20 | * Trolling, insulting/derogatory comments, and personal or political attacks
21 | * Public or private harassment
22 | * Publishing others' private information, such as a physical or electronic address, without explicit permission
23 | * Other conduct which could reasonably be considered inappropriate in a professional setting
24 |
25 | ## Our Responsibilities
26 |
27 | Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior.
28 |
29 | Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful.
30 |
31 | ## Scope
32 |
33 | This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers.
34 |
35 | ## Enforcement
36 |
37 | Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at info@recommenders.net. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately.
38 |
39 | Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership.
40 |
41 | ## Attribution
42 |
43 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version]
44 |
45 | [homepage]: http://contributor-covenant.org
46 | [version]: http://contributor-covenant.org/version/1/4/
47 |
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | We're very happy if you want to contribute to RiVal. If you are not sure on what to work on, have a look a the current [issues](/../../issues/).
2 |
3 | If you have any questions on how to use RiVal, you may get ann answer by asking on the
4 | the RiVal [mailing list](https://groups.google.com/forum/#!forum/rival-user) or [Gitter chat room](https://gitter.im/recommenders/rival
5 | ).
6 |
7 |
8 | If you want to contribute, do it in the form of GitHub pull requests. To do this:
9 |
10 | 1. Find the [issue](/../../issues/) you want to fix, or create a new one describing what your contribution fixes.
11 | 1. Fork RiVal [rival](/../../) on GitHub
12 | 2. Push your changes to your fork
13 | 3. Submit a pull request via the GitHub Web interface
14 |
15 | Note that all your contributions will be licensed under RiVal's copyright licences (Apache). If you are committing a new class, make sure to include the copyright statement at the top.
16 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # RiVal
2 |
3 |
4 | [](https://travis-ci.org/recommenders/rival)
5 | [](https://gitter.im/recommenders/rival?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
6 | [](https://codecov.io/gh/recommenders/rival)
7 | [](https://opensource.org/licenses/Apache-2.0)
8 |
9 |
10 |
11 | **RiVal** is a toolkit for data splitting and evaluation of recommender systems. This page contains information on how to work with the RiVal code and how to compile RiVal.
12 | For more information about RiVal and the documentation, visit the RiVal [website](http://rival.recommenders.net) or [wiki][].
13 | If you have not used RiVal before, do check out the [Getting Started][] guide.
14 |
15 | [website]: http://rival.recommenders.net
16 | [wiki]: http://github.com/recommenders/rival/wiki/
17 | [Getting Started]: http://github.com/recommenders/rival/wiki/GettingStarted
18 |
19 | RiVal is made available under Apache License, Version 2.0.
20 |
21 | ## Installation and Dependency Management
22 |
23 | RiVal is built and deployed via [Maven][]. In order to install it, check out
24 | this repository and run `mvn install`. This will make it available for other Maven projects as a dependency.
25 |
26 | [Maven]: http://maven.apache.org
27 |
28 | ## Modules
29 |
30 | RiVal is comprised of one top-level module and four sub-modules. The top-level `rival`
31 | module is a container module used to build the submodules and provide all needed settings
32 | and dependencies. The five sub-modules are as follows:
33 |
34 | * `rival-core` -- the common data structures and similar object used throughout RiVal.
35 | * `rival-evaluate` -- the evaluation module, contains metrics and strategies used for evaluation.
36 | * `rival-examples` -- a module containing examples on how to use RiVal programmatically.
37 | * `rival-recommend` -- the recommendation modeule, contains hooks to Apache Mahout and LensKit.
38 | * `rival-split` -- the data splitting module, contains different data splitting strategies.
39 | * `rival-package` -- a configuration module for bulding rival distributions.
40 |
41 | ## Contributing to RiVal
42 |
43 | We're very happy if you want to contribute to RiVal. If you are not sure on what to work on, have a look a the current [issues](/../../issues/).
44 |
45 | If you want to contribute, do it in the form of GitHub pull requests. To do this:
46 |
47 |
48 | 1. Find the [issue](/../../issues/) you want to fix, or create a new one describing what your contribution fixes.
49 | 1. Fork RiVal [rival](/../../) on GitHub
50 | 2. Push your changes to your fork
51 | 3. Submit a pull request via the GitHub Web interface
52 |
53 | Note that all your contributions will be licensed under RiVal's copyright licences (Apache). If you are committing a new class, make sure to include the copyright statement at the top.
54 |
55 | ## Mailing list
56 |
57 | To subscribe to the rival mailing list, visit and join the [rival-users](https://groups.google.com/forum/#!forum/rival-user) Google group.
58 |
59 | ## More information
60 | * [RiVal website](http://rival.recommenders.net)
61 | * RiVal in [research](../../wiki/Research)
62 | * RiVal on [Maven central](http://search.maven.org/#search%7Cga%7C1%7Cnet.recommenders.rival)
63 |
--------------------------------------------------------------------------------
/codecov.yml:
--------------------------------------------------------------------------------
1 |
2 | codecov:
3 | branch: master
4 | bot: null
5 |
6 | coverage:
7 | precision: 2
8 | round: down
9 | range: "70...100"
10 |
11 | notify:
12 | slack:
13 | default:
14 | url: null
15 | threshold: null
16 | branches: null
17 | attachments: "sunburst, diff"
18 |
19 | hipchat:
20 | default:
21 | url: null
22 | notify: no
23 | threshold: null
24 | branches: null
25 | card: yes
26 | only_pulls: null
27 | message: null
28 |
29 | gitter:
30 | default:
31 | url: null
32 | threshold: null
33 | branches: null
34 | message: null
35 |
36 | webhook:
37 | default:
38 | url: null
39 | threshold: null
40 | branches: null
41 | only_pulls: null
42 |
43 | irc:
44 | default:
45 | server: null
46 | channel: null
47 | branches: null
48 | threshold: null
49 | message: null
50 |
51 | status:
52 | project:
53 | default:
54 | target: auto
55 | threshold: null
56 | branches: null
57 |
58 | patch:
59 | default:
60 | target: auto
61 | branches: null
62 |
63 | changes:
64 | default:
65 | branches: null
66 |
67 | ignore: null
68 |
69 | comment:
70 | layout: "header, diff, changes, sunburst, uncovered, tree"
71 | branches: null
72 | behavior: default
73 |
--------------------------------------------------------------------------------
/rival-core/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 4.0.0
4 |
5 |
6 | rival
7 | net.recommenders.rival
8 | 0.3-SNAPSHOT
9 |
10 | rival-core
11 | jar
12 | RiVal Core
13 |
14 |
15 |
16 | junit
17 | junit
18 |
19 |
20 |
21 | org.apache.commons
22 | commons-csv
23 | 1.0
24 |
25 |
26 |
27 | org.apache.mahout
28 | mahout-core
29 | ${mahout.version}
30 |
31 |
32 | asm
33 | asm
34 |
35 |
36 | commons-lang
37 | commons-lang
38 |
39 |
40 |
41 |
42 |
43 | org.ranksys.RankSys
44 | RankSys-core
45 | ${ranksys.version}
46 |
47 |
48 | org.ranksys.RankSys
49 | RankSys-fast
50 | ${ranksys.version}
51 |
52 |
53 |
--------------------------------------------------------------------------------
/rival-core/src/main/java/net/recommenders/rival/core/AbstractParser.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2015 recommenders.net.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package net.recommenders.rival.core;
17 |
18 | /**
19 | * Abstract class for datamodel parsers.
20 | *
21 | * @author Alan.
22 | */
23 | public abstract class AbstractParser {
24 |
25 | /**
26 | * Default for the column index for the user id in the file.
27 | */
28 | public static final int USER_TOK = 0;
29 | /**
30 | * Default for the column index for the item id in the file.
31 | */
32 | public static final int ITEM_TOK = 1;
33 | /**
34 | * Default for the column index for the interaction value (e.g. rating) in
35 | * the file.
36 | */
37 | public static final int PREFERENCE_TOK = 2;
38 | /**
39 | * Default for the column index for the timestamp in the file.
40 | */
41 | public static final int TIME_TOK = 3;
42 | /**
43 | * Default for whether the file contains a column header.
44 | */
45 | public static final boolean HAS_HEADER = false;
46 | /**
47 | * Default for the column delimiter.
48 | */
49 | public static final char DELIMITER = ',';
50 | /**
51 | * The column index for the user id in the file.
52 | */
53 | private int userTok;
54 | /**
55 | * The column index for the item id in the file.
56 | */
57 | private int itemTok;
58 | /**
59 | * The column index for the interaction value (e.g. rating) in the file.
60 | */
61 | private int prefTok;
62 | /**
63 | * The column index for the timestamp in the file.
64 | */
65 | private int timeTok;
66 | /**
67 | * Whether the file contains a column header.
68 | */
69 | private boolean hasHeader;
70 | /**
71 | * The column delimiter.
72 | */
73 | private char delimiter;
74 |
75 | /**
76 | * Default constructor.
77 | */
78 | public AbstractParser() {
79 | this.userTok = USER_TOK;
80 | this.itemTok = ITEM_TOK;
81 | this.prefTok = PREFERENCE_TOK;
82 | this.timeTok = TIME_TOK;
83 | this.hasHeader = HAS_HEADER;
84 | this.delimiter = DELIMITER;
85 | }
86 |
87 | /**
88 | * Gets the delimiter.
89 | *
90 | * @return the delimiter
91 | */
92 | public char getDelimiter() {
93 | return delimiter;
94 | }
95 |
96 | /**
97 | * Checks if this parser has a header.
98 | *
99 | * @return true if it has a header
100 | */
101 | public boolean isHasHeader() {
102 | return hasHeader;
103 | }
104 |
105 | /**
106 | * Gets the column index for items.
107 | *
108 | * @return the column index for items
109 | */
110 | public int getItemTok() {
111 | return itemTok;
112 | }
113 |
114 | /**
115 | * Gets the column index for preferences.
116 | *
117 | * @return the column index for preferences
118 | */
119 | public int getPrefTok() {
120 | return prefTok;
121 | }
122 |
123 | /**
124 | * Gets the column index for time.
125 | *
126 | * @return the column index for time
127 | */
128 | public int getTimeTok() {
129 | return timeTok;
130 | }
131 |
132 | /**
133 | * Gets the column index for users.
134 | *
135 | * @return the column index for users
136 | */
137 | public int getUserTok() {
138 | return userTok;
139 | }
140 |
141 | /**
142 | * Sets the field delimiter.
143 | *
144 | * @param del the delimiter between fields
145 | */
146 | public void setDelimiter(final char del) {
147 | this.delimiter = del;
148 | }
149 |
150 | /**
151 | * Sets the flag indicating whether the file has a header.
152 | *
153 | * @param header flag indicating whether the file has a header
154 | */
155 | public void setHasHeader(final boolean header) {
156 | this.hasHeader = header;
157 | }
158 |
159 | /**
160 | * Sets the column index for items.
161 | *
162 | * @param itemToken the column index for items
163 | */
164 | public void setItemTok(final int itemToken) {
165 | this.itemTok = itemToken;
166 | }
167 |
168 | /**
169 | * Sets the column index for preferences.
170 | *
171 | * @param prefToken the column index for preferences
172 | */
173 | public void setPrefTok(final int prefToken) {
174 | this.prefTok = prefToken;
175 | }
176 |
177 | /**
178 | * Sets the column index for time.
179 | *
180 | * @param timeToken the column index for time
181 | */
182 | public void setTimeTok(final int timeToken) {
183 | this.timeTok = timeToken;
184 | }
185 |
186 | /**
187 | * Sets the column index for users.
188 | *
189 | * @param userToken the column index for users
190 | */
191 | public void setUserTok(final int userToken) {
192 | this.userTok = userToken;
193 | }
194 | }
195 |
--------------------------------------------------------------------------------
/rival-core/src/main/java/net/recommenders/rival/core/DataModelFactory.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2016 recommenders.net.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package net.recommenders.rival.core;
17 |
18 | import net.recommenders.rival.core.ext.MahoutDataModel;
19 | import net.recommenders.rival.core.ext.RankSysDataModel;
20 |
21 | /**
22 | *
23 | * @author Alejandro
24 | */
25 | public class DataModelFactory {
26 |
27 | public static DataModelIF getDefaultModel() {
28 | return getSimpleModel();
29 | }
30 |
31 | public static TemporalDataModelIF getDefaultTemporalModel() {
32 | return getSimpleTemporalModel();
33 | }
34 |
35 | public static DataModelIF getSimpleModel() {
36 | return new DataModel<>();
37 | }
38 |
39 | public static TemporalDataModelIF getSimpleTemporalModel() {
40 | return new TemporalDataModel<>();
41 | }
42 |
43 | public static TemporalDataModelIF getMahoutTemporalModel() {
44 | return new MahoutDataModel();
45 | }
46 |
47 | public static DataModelIF getRankSysModel() {
48 | return new RankSysDataModel<>();
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/rival-core/src/main/java/net/recommenders/rival/core/DataModelIF.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2015 recommenders.net.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package net.recommenders.rival.core;
17 |
18 | /**
19 | * Interface for the data model used throughout the toolkit. Able to store
20 | * users, items, and preferences.
21 | *
22 | * @author Alejandro, Alan
24 | *
25 | * @param generic type for users
26 | * @param generic type for items
27 | */
28 | public interface DataModelIF {
29 |
30 | /**
31 | * Method that returns the preference between a user and an item.
32 | *
33 | * @param u the user.
34 | * @param i the item.
35 | * @return the preference between a user and an item.
36 | */
37 | public Double getUserItemPreference(U u, I i);
38 |
39 | /**
40 | * Method that returns the items of a user.
41 | *
42 | * @param u the user.
43 | * @return the items of a user.
44 | */
45 | public Iterable getUserItems(U u);
46 |
47 | /**
48 | * Method that adds a preference to the model between a user and an item.
49 | *
50 | * @param u the user.
51 | * @param i the item.
52 | * @param d the preference.
53 | */
54 | public void addPreference(final U u, final I i, final Double d);
55 |
56 | /**
57 | * Method that returns the items in the model.
58 | *
59 | * @return the items in the model.
60 | */
61 | public Iterable getItems();
62 |
63 | /**
64 | * Method that returns the users in the model.
65 | *
66 | * @return the users in the model.
67 | */
68 | public Iterable getUsers();
69 |
70 | /**
71 | * Method that returns the number of items in the model.
72 | *
73 | * @return the number of items in the model.
74 | */
75 | public int getNumItems();
76 |
77 | /**
78 | * Method that returns the number of users in the model.
79 | *
80 | * @return the number of users in the model.
81 | */
82 | public int getNumUsers();
83 |
84 | /**
85 | * Method that clears all the maps contained in the model.
86 | */
87 | public void clear();
88 | }
89 |
--------------------------------------------------------------------------------
/rival-core/src/main/java/net/recommenders/rival/core/DataModelUtils.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2015 recommenders.net.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package net.recommenders.rival.core;
17 |
18 | import java.io.File;
19 | import java.io.FileNotFoundException;
20 | import java.io.PrintStream;
21 | import java.io.UnsupportedEncodingException;
22 |
23 | /**
24 | * Utilities for datamodels.
25 | *
26 | * @author Alan.
27 | */
28 | public final class DataModelUtils {
29 |
30 | /**
31 | * Utility classes should not have a public constructor.
32 | */
33 | private DataModelUtils() {
34 | }
35 |
36 | /**
37 | * Method that saves a data model to a file.
38 | *
39 | * @param dm the data model
40 | * @param outfile file where the model will be saved
41 | * @param overwrite flag that indicates if the file should be overwritten
42 | * @param delimiter field delimiter
43 | * @param type of users
44 | * @param type of items
45 | * @throws FileNotFoundException when outfile cannot be used.
46 | * @throws UnsupportedEncodingException when the requested encoding (UTF-8)
47 | * is not available.
48 | */
49 | public static void saveDataModel(final DataModelIF dm, final String outfile, final boolean overwrite, final String delimiter)
50 | throws FileNotFoundException, UnsupportedEncodingException {
51 | if (new File(outfile).exists() && !overwrite) {
52 | System.out.println("Ignoring " + outfile);
53 | } else {
54 | PrintStream out = new PrintStream(outfile, "UTF-8");
55 | for (U user : dm.getUsers()) {
56 | for (I item : dm.getUserItems(user)) {
57 | Double pref = dm.getUserItemPreference(user, item);
58 | out.println(user + delimiter + item + delimiter + pref);
59 | }
60 | }
61 | out.close();
62 | }
63 | }
64 |
65 | /**
66 | * Method that saves a temporal data model to a file.
67 | *
68 | * @param dm the data model
69 | * @param outfile file where the model will be saved
70 | * @param overwrite flag that indicates if the file should be overwritten
71 | * @param delimiter field delimiter
72 | * @param type of users
73 | * @param type of items
74 | * @throws FileNotFoundException when outfile cannot be used.
75 | * @throws UnsupportedEncodingException when the requested encoding (UTF-8)
76 | * is not available.
77 | */
78 | public static void saveDataModel(final TemporalDataModelIF dm, final String outfile, final boolean overwrite, String delimiter)
79 | throws FileNotFoundException, UnsupportedEncodingException {
80 | if (new File(outfile).exists() && !overwrite) {
81 | System.out.println("Ignoring " + outfile);
82 | } else {
83 | PrintStream out = new PrintStream(outfile, "UTF-8");
84 | for (U user : dm.getUsers()) {
85 | for (I item : dm.getUserItems(user)) {
86 | Double pref = dm.getUserItemPreference(user, item);
87 | Iterable time = dm.getUserItemTimestamps(user, item);
88 | if (time == null) {
89 | out.println(user + delimiter + item + delimiter + pref + delimiter + "-1");
90 | } else {
91 | for (Long t : time) {
92 | out.println(user + delimiter + item + delimiter + pref + delimiter + t);
93 | }
94 | }
95 | }
96 | }
97 | out.close();
98 | }
99 | }
100 | }
101 |
--------------------------------------------------------------------------------
/rival-core/src/main/java/net/recommenders/rival/core/Parser.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2015 recommenders.net.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package net.recommenders.rival.core;
17 |
18 | import java.io.File;
19 | import java.io.IOException;
20 |
21 | /**
22 | * Data model parser interface.
23 | *
24 | * @author Alejandro
25 | *
26 | * @param generic type of users
27 | * @param generic type of items
28 | */
29 | public interface Parser {
30 |
31 | /**
32 | * Parse a temporal data file.
33 | *
34 | * @param f The file to be parsed.
35 | * @return A dataset created from the file.
36 | * @throws IOException if the file cannot be read.
37 | */
38 | TemporalDataModelIF parseTemporalData(File f) throws IOException;
39 |
40 | /**
41 | * Parse a data file.
42 | *
43 | * @param f The file to be parsed.
44 | * @return A dataset created from the file.
45 | * @throws IOException if the file cannot be read.
46 | */
47 | DataModelIF parseData(File f) throws IOException;
48 | }
49 |
--------------------------------------------------------------------------------
/rival-core/src/main/java/net/recommenders/rival/core/ParserWithIdMapping.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2015 recommenders.net.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package net.recommenders.rival.core;
17 |
18 | import java.io.File;
19 | import java.io.IOException;
20 |
21 | /**
22 | * Parser of files where users or items are not represented as integer ids.
23 | *
24 | * @author Alejandro
25 | *
26 | * @param generic type of users
27 | * @param generic type of items
28 | */
29 | public interface ParserWithIdMapping extends Parser {
30 |
31 | /**
32 | * Parse a temporal data file.
33 | *
34 | * @param f The file to be parsed.
35 | * @param mapIdsPrefix The prefix of the file where the id mapping will be
36 | * stored (and will be read from).
37 | * @return A dataset created from the file.
38 | * @throws IOException if the file cannot be read.
39 | */
40 | TemporalDataModelIF parseTemporalData(File f, String mapIdsPrefix) throws IOException;
41 |
42 | /**
43 | * Parse data file.
44 | *
45 | * @param f The file to parse.
46 | * @param mapIdsPrefix The prefix of the file where the id mapping will be
47 | * stored (and will be read from).
48 | * @return The data model created from the file.
49 | * @throws IOException if the file cannot be read.
50 | */
51 | DataModelIF parseData(File f, String mapIdsPrefix) throws IOException;
52 | }
53 |
--------------------------------------------------------------------------------
/rival-core/src/main/java/net/recommenders/rival/core/SimpleParser.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2015 recommenders.net.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package net.recommenders.rival.core;
17 |
18 | import java.io.BufferedReader;
19 | import java.io.File;
20 | import java.io.FileInputStream;
21 | import java.io.IOException;
22 | import java.io.InputStreamReader;
23 | import java.util.zip.GZIPInputStream;
24 |
25 | /**
26 | * Data parser for tab-separated data files.
27 | *
28 | * @author Alejandro
29 | */
30 | public class SimpleParser implements Parser {
31 |
32 | /**
33 | * The column index for the user id in the file.
34 | */
35 | public static final int USER_TOK = 0;
36 | /**
37 | * The column index for the item id in the file.
38 | */
39 | public static final int ITEM_TOK = 1;
40 | /**
41 | * The column index for the rating in the file.
42 | */
43 | public static final int RATING_TOK = 2;
44 | /**
45 | * The column index for the time in the file.
46 | */
47 | public static final int TIME_TOK = 3;
48 |
49 | /**
50 | * {@inheritDoc}
51 | */
52 | @Override
53 | public DataModelIF parseData(final File f) throws IOException {
54 | return parseData(f, "\t", false);
55 | }
56 |
57 | /**
58 | * {@inheritDoc}
59 | */
60 | @Override
61 | public TemporalDataModelIF parseTemporalData(final File f) throws IOException {
62 | return parseData(f, "\t", true);
63 | }
64 |
65 | /**
66 | * Parses a data file with a specific separator between fields.
67 | *
68 | * @param f The file to be parsed.
69 | * @param token The separator to be used.
70 | * @param isTemporal A flag indicating if the file contains temporal
71 | * information.
72 | * @return A dataset created from the file.
73 | * @throws IOException if the file cannot be read.
74 | */
75 | public TemporalDataModelIF parseData(final File f, final String token, final boolean isTemporal) throws IOException {
76 | TemporalDataModelIF dataset = DataModelFactory.getDefaultTemporalModel();
77 |
78 | BufferedReader br = SimpleParser.getBufferedReader(f);
79 | String line = br.readLine();
80 | if ((line != null) && (!line.matches(".*[a-zA-Z].*"))) {
81 | parseLine(line, dataset, token, isTemporal);
82 | }
83 | while ((line = br.readLine()) != null) {
84 | parseLine(line, dataset, token, isTemporal);
85 | }
86 | br.close();
87 |
88 | return dataset;
89 | }
90 |
91 | /**
92 | * Obtains an instance of BufferedReader depending on the file extension: if
93 | * it ends with gz, zip, or tgz then a compressed reader is used instead of
94 | * the standard one.
95 | *
96 | * @param f The file to be opened.
97 | * @return An instance of BufferedReader or null if there is a problem
98 | * @throws IOException when the file cannot be read.
99 | * @see BufferedReader
100 | */
101 | public static BufferedReader getBufferedReader(final File f) throws IOException {
102 | BufferedReader br = null;
103 | if ((f == null) || (!f.isFile())) {
104 | return br;
105 | }
106 | if (f.getName().endsWith(".gz") || f.getName().endsWith(".zip") || f.getName().endsWith(".tgz")) {
107 | br = new BufferedReader(new InputStreamReader(new GZIPInputStream(new FileInputStream(f)), "UTF-8"));
108 | } else {
109 | br = new BufferedReader(new InputStreamReader(new FileInputStream(f), "UTF-8"));
110 | }
111 | return br;
112 | }
113 |
114 | /**
115 | * Parses line from data file.
116 | *
117 | * @param line The line to be parsed.
118 | * @param dataset The dataset to add data from line to.
119 | * @param token the token to split on.
120 | * @param isTemporal A flag indicating if the line contains temporal
121 | * information.
122 | */
123 | private void parseLine(final String line, final TemporalDataModelIF dataset, final String token, final boolean isTemporal) {
124 | if (line == null) {
125 | return;
126 | }
127 | String[] toks = line.split(token);
128 | // user
129 | long userId = Long.parseLong(toks[USER_TOK]);
130 | // item
131 | long itemId = Long.parseLong(toks[ITEM_TOK]);
132 | // preference
133 | double preference = Double.parseDouble(toks[RATING_TOK]);
134 | // timestamp
135 | long timestamp = -1;
136 | // allow no timestamp information
137 | if (isTemporal && toks.length > TIME_TOK) {
138 | timestamp = Long.parseLong(toks[TIME_TOK]);
139 | }
140 | //////
141 | // update information
142 | //////
143 | dataset.addPreference(userId, itemId, preference);
144 | if (timestamp != -1) {
145 | dataset.addTimestamp(userId, itemId, timestamp);
146 | }
147 | }
148 | }
149 |
--------------------------------------------------------------------------------
/rival-core/src/main/java/net/recommenders/rival/core/TemporalDataModel.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2015 recommenders.net.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package net.recommenders.rival.core;
17 |
18 | import java.util.HashMap;
19 | import java.util.HashSet;
20 | import java.util.Map;
21 | import java.util.Set;
22 |
23 | /**
24 | * Temporal data model used throughout the toolkit. It is able to store users,
25 | * items, preferences, and timestamps.
26 | *
27 | * @author Alejandro, Alan
29 | *
30 | * @param generic type for users
31 | * @param generic type for items
32 | */
33 | public class TemporalDataModel extends DataModel implements TemporalDataModelIF {
34 |
35 | /**
36 | * The map with the timestamps between users and items.
37 | */
38 | protected Map>> userItemTimestamps;
39 |
40 | /**
41 | * Default constructor.
42 | */
43 | public TemporalDataModel() {
44 | super();
45 | userItemTimestamps = new HashMap<>();
46 | }
47 |
48 | /**
49 | * Constructor with parameters.
50 | *
51 | * @param ignoreDupPreferences The flag to indicate whether preferences
52 | * should be ignored.
53 | */
54 | public TemporalDataModel(final boolean ignoreDupPreferences) {
55 | super(ignoreDupPreferences);
56 | userItemTimestamps = new HashMap<>();
57 | }
58 |
59 | /**
60 | * Constructor with parameters.
61 | *
62 | * @param ignoreDupPreferences The flag to indicate whether preferences
63 | * should be ignored.
64 | * @param userItemPreference The preference map between users and items.
65 | * @param itemSet The items.
66 | * @param userItemTimestamp The map with the timestamps between users and
67 | * items
68 | */
69 | public TemporalDataModel(final boolean ignoreDupPreferences, final Map> userItemPreference, final Set itemSet,
70 | final Map>> userItemTimestamp) {
71 | super(ignoreDupPreferences, userItemPreference, itemSet);
72 | this.userItemTimestamps = userItemTimestamp;
73 | }
74 |
75 | /**
76 | * Method that returns the map with the timestamps between users and items.
77 | *
78 | * @return the map with the timestamps between users and items.
79 | */
80 | @Override
81 | public Iterable getUserItemTimestamps(U u, I i) {
82 | if (userItemTimestamps.containsKey(u) && userItemTimestamps.get(u).containsKey(i)) {
83 | return userItemTimestamps.get(u).get(i);
84 | }
85 | return null;
86 | }
87 |
88 | /**
89 | * Method that adds a timestamp to the model between a user and an item.
90 | *
91 | * @param u the user.
92 | * @param i the item.
93 | * @param t the timestamp.
94 | */
95 | @Override
96 | public void addTimestamp(final U u, final I i, final Long t) {
97 | Map> userTimestamps = userItemTimestamps.get(u);
98 | if (userTimestamps == null) {
99 | userTimestamps = new HashMap<>();
100 | userItemTimestamps.put(u, userTimestamps);
101 | }
102 | Set timestamps = userTimestamps.get(i);
103 | if (timestamps == null) {
104 | timestamps = new HashSet<>();
105 | userTimestamps.put(i, timestamps);
106 | }
107 | timestamps.add(t);
108 | }
109 |
110 | /**
111 | * Method that clears all the maps contained in the model.
112 | */
113 | public void clear() {
114 | super.clear();
115 | userItemTimestamps.clear();
116 | }
117 | }
118 |
--------------------------------------------------------------------------------
/rival-core/src/main/java/net/recommenders/rival/core/TemporalDataModelIF.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2015 recommenders.net.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package net.recommenders.rival.core;
17 |
18 | /**
19 | * Interface for a temporal data model. It is able to store users, items,
20 | * preferences, and timestamps.
21 | *
22 | * @author Alejandro, Alan
24 | *
25 | * @param generic type for users
26 | * @param generic type for items
27 | */
28 | public interface TemporalDataModelIF extends DataModelIF {
29 |
30 | /**
31 | * Method that returns the timestamps between a user and an item.
32 | *
33 | * @param u the user.
34 | * @param i the item.
35 | * @return the timestamps between a user and an item.
36 | */
37 | public Iterable getUserItemTimestamps(U u, I i);
38 |
39 | /**
40 | * Method that adds a timestamp to the model between a user and an item.
41 | *
42 | * @param u the user.
43 | * @param i the item.
44 | * @param t the timestamp.
45 | */
46 | public void addTimestamp(final U u, final I i, final Long t);
47 | }
48 |
--------------------------------------------------------------------------------
/rival-core/src/main/java/net/recommenders/rival/core/UIPParser.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2015 recommenders.net.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package net.recommenders.rival.core;
17 |
18 | import org.apache.commons.csv.CSVFormat;
19 | import org.apache.commons.csv.CSVRecord;
20 |
21 | import java.io.File;
22 | import java.io.FileInputStream;
23 | import java.io.Reader;
24 | import java.io.IOException;
25 | import java.io.InputStreamReader;
26 |
27 | /**
28 | * User-Item-Preference (rating) Parser.
29 | *
30 | * @author Alan.
31 | */
32 | public class UIPParser extends AbstractParser implements Parser {
33 |
34 | /**
35 | * Default constructor.
36 | */
37 | public UIPParser() {
38 | super();
39 | }
40 |
41 | /**
42 | * {@inheritDoc}
43 | */
44 | @Override
45 | public TemporalDataModelIF parseTemporalData(final File f) throws IOException {
46 | TemporalDataModelIF dataset = DataModelFactory.getDefaultTemporalModel();
47 | Reader in = new InputStreamReader(new FileInputStream(f), "UTF-8");
48 |
49 | Iterable records;
50 | if (isHasHeader()) {
51 | records = CSVFormat.EXCEL.withDelimiter(getDelimiter()).withHeader().parse(in);
52 | } else {
53 | records = CSVFormat.EXCEL.withDelimiter(getDelimiter()).parse(in);
54 | }
55 | for (CSVRecord record : records) {
56 | long userID = Long.parseLong(record.get(getUserTok()));
57 | long itemID = Long.parseLong(record.get(getItemTok()));
58 | long timestamp = -1L;
59 | if (getTimeTok() != -1) {
60 | timestamp = Long.parseLong(record.get(getTimeTok()));
61 | }
62 | double preference = Double.parseDouble(record.get(getPrefTok()));
63 | dataset.addPreference(userID, itemID, preference);
64 | dataset.addTimestamp(userID, itemID, timestamp);
65 | }
66 | in.close();
67 | return dataset;
68 | }
69 |
70 | /**
71 | * {@inheritDoc}
72 | */
73 | @Override
74 | public DataModelIF parseData(final File f) throws IOException {
75 | DataModelIF dataset = new DataModel<>();
76 | Reader in = new InputStreamReader(new FileInputStream(f), "UTF-8");
77 |
78 | Iterable records;
79 | if (isHasHeader()) {
80 | records = CSVFormat.EXCEL.withDelimiter(getDelimiter()).withHeader().parse(in);
81 | } else {
82 | records = CSVFormat.EXCEL.withDelimiter(getDelimiter()).parse(in);
83 | }
84 | for (CSVRecord record : records) {
85 | long userID = Long.parseLong(record.get(getUserTok()));
86 | long itemID = Long.parseLong(record.get(getItemTok()));
87 | double preference = Double.parseDouble(record.get(getPrefTok()));
88 | dataset.addPreference(userID, itemID, preference);
89 | }
90 | in.close();
91 | return dataset;
92 | }
93 | }
94 |
--------------------------------------------------------------------------------
/rival-core/src/main/java/net/recommenders/rival/core/ext/RankSysDataModel.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2016 recommenders.net.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package net.recommenders.rival.core.ext;
17 |
18 | import es.uam.eps.ir.ranksys.fast.index.FastItemIndex;
19 | import es.uam.eps.ir.ranksys.fast.index.FastUserIndex;
20 | import es.uam.eps.ir.ranksys.fast.index.SimpleFastItemIndex;
21 | import es.uam.eps.ir.ranksys.fast.index.SimpleFastUserIndex;
22 | import es.uam.eps.ir.ranksys.fast.preference.SimpleFastPreferenceData;
23 | import java.util.ArrayList;
24 | import java.util.HashSet;
25 | import java.util.Iterator;
26 | import java.util.List;
27 | import java.util.NoSuchElementException;
28 | import java.util.Set;
29 | import java.util.stream.Stream;
30 | import net.recommenders.rival.core.DataModelIF;
31 | import org.jooq.lambda.tuple.Tuple;
32 | import org.jooq.lambda.tuple.Tuple3;
33 |
34 | /**
35 | *
36 | * @author Alejandro
37 | */
38 | public class RankSysDataModel implements DataModelIF {
39 |
40 | private SimpleFastPreferenceData model;
41 | private List> tuples;
42 | private Set users;
43 | private Set items;
44 |
45 | public RankSysDataModel() {
46 | clear();
47 | }
48 |
49 | private void generateDatamodel() {
50 | FastUserIndex uIndex = SimpleFastUserIndex.load(users.stream());
51 | FastItemIndex iIndex = SimpleFastItemIndex.load(items.stream());
52 | model = SimpleFastPreferenceData.load(tuples.stream(), uIndex, iIndex);
53 | }
54 |
55 | @Override
56 | public void addPreference(U u, I i, Double d) {
57 | if (model != null) {
58 | throw new IllegalArgumentException("DataModel already generated. It is not possible to add more information.");
59 | }
60 | users.add(u);
61 | items.add(i);
62 | tuples.add(Tuple.tuple(u, i, d));
63 | }
64 |
65 | @Override
66 | public Double getUserItemPreference(U u, I i) {
67 | if (model == null) {
68 | generateDatamodel();
69 | }
70 | try {
71 | return model.getPreference(u, i).get().v2;
72 | } catch (NoSuchElementException e) {
73 | return Double.NaN;
74 | }
75 | }
76 |
77 | @Override
78 | public Iterable getUserItems(U u) {
79 | if (model == null) {
80 | generateDatamodel();
81 | }
82 | Stream s = model.getUserPreferences(u).map(p -> p.v1());
83 | return new Iterable() {
84 | @Override
85 | public Iterator iterator() {
86 | return s.iterator();
87 | }
88 | };
89 | }
90 |
91 | @Override
92 | public Iterable getItems() {
93 | if (model == null) {
94 | generateDatamodel();
95 | }
96 | Stream s = model.getItemsWithPreferences();
97 | return new Iterable() {
98 | @Override
99 | public Iterator iterator() {
100 | return s.iterator();
101 | }
102 | };
103 | }
104 |
105 | @Override
106 | public Iterable getUsers() {
107 | if (model == null) {
108 | generateDatamodel();
109 | }
110 | Stream s = model.getUsersWithPreferences();
111 | return new Iterable() {
112 | @Override
113 | public Iterator iterator() {
114 | return s.iterator();
115 | }
116 | };
117 | }
118 |
119 | @Override
120 | public int getNumItems() {
121 | if (model == null) {
122 | generateDatamodel();
123 | }
124 | return model.numItems();
125 | }
126 |
127 | @Override
128 | public int getNumUsers() {
129 | if (model == null) {
130 | generateDatamodel();
131 | }
132 | return model.numUsers();
133 | }
134 |
135 | @Override
136 | public void clear() {
137 | model = null;
138 | tuples = new ArrayList<>();
139 | users = new HashSet<>();
140 | items = new HashSet<>();
141 | }
142 | }
143 |
--------------------------------------------------------------------------------
/rival-core/src/main/java/net/recommenders/rival/core/package-info.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Core API classes for RiVal.
3 | */
4 | package net.recommenders.rival.core;
5 |
--------------------------------------------------------------------------------
/rival-core/src/test/java/net/recommenders/rival/core/DataModelTest.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2015 recommenders.net.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package net.recommenders.rival.core;
17 |
18 | import static org.junit.Assert.assertEquals;
19 |
20 | import org.junit.Before;
21 | import org.junit.Test;
22 | import org.junit.runner.RunWith;
23 | import org.junit.runners.JUnit4;
24 |
25 | /**
26 | * Tests for {@link net.recommenders.rival.core.DataModel}.
27 | *
28 | * @author Alan
29 | */
30 | @RunWith(JUnit4.class)
31 | public class DataModelTest {
32 |
33 | /**
34 | * The data model.
35 | */
36 | private DataModel dm = new DataModel<>();
37 | /**
38 | * The number of users in the data model.
39 | */
40 | private static final int USERS = 3;
41 | /**
42 | * The number of items in the data model.
43 | */
44 | private static final int ITEMS = 3;
45 |
46 | @Before
47 | public void initialize() {
48 | for (long u = 1L; u <= USERS; u++) {
49 | for (long i = 1L; i <= ITEMS; i++) {
50 | dm.addPreference(u, i, 1.0 * u * i);
51 | }
52 | }
53 | }
54 |
55 | @Test
56 | public void testGetUserPreferences() {
57 | for (long u = 1L; u <= USERS; u++) {
58 | for (long i = 1L; i <= ITEMS; i++) {
59 | assertEquals(1.0 * u * i, dm.getUserItemPreference(u, i), 0.0);
60 | }
61 | }
62 | }
63 |
64 | @Test
65 | public void testGetNumItems() {
66 | assertEquals(ITEMS, dm.getNumItems());
67 | }
68 |
69 | @Test
70 | public void testGetNumUsers() {
71 | assertEquals(USERS, dm.getNumUsers());
72 | }
73 |
74 | @Test
75 | public void testGetItems() {
76 | assertEquals(ITEMS, dm.getNumItems());
77 | }
78 |
79 | @Test
80 | public void testClearItems() {
81 | dm.clear();
82 | assertEquals(0, dm.getNumItems());
83 | }
84 |
85 | @Test
86 | public void testDuplicatePreferences() {
87 | DataModel unconstrainedModel = new DataModel<>();
88 | for (long u = 1L; u <= USERS; u++) {
89 | for (long i = 1L; i <= ITEMS; i++) {
90 | unconstrainedModel.addPreference(u, i, 1.0 * u * i);
91 | }
92 | // duplicate preferences
93 | for (long i = 1L; i <= ITEMS; i++) {
94 | unconstrainedModel.addPreference(u, i, 1.0 * u * i);
95 | }
96 | }
97 | for (long u = 1L; u <= USERS; u++) {
98 | for (long i = 1L; i <= ITEMS; i++) {
99 | assertEquals(2.0 * u * i, unconstrainedModel.getUserItemPreference(u, i), 0.0);
100 | }
101 | }
102 | DataModel constrainedModel = new DataModel<>(true);
103 | for (long u = 1L; u <= USERS; u++) {
104 | for (long i = 1L; i <= ITEMS; i++) {
105 | constrainedModel.addPreference(u, i, 1.0 * u * i);
106 | }
107 | // duplicate preferences
108 | for (long i = 1L; i <= ITEMS; i++) {
109 | constrainedModel.addPreference(u, i, 1.0 * u * i);
110 | }
111 | }
112 | for (long u = 1L; u <= USERS; u++) {
113 | for (long i = 1L; i <= ITEMS; i++) {
114 | assertEquals(1.0 * u * i, constrainedModel.getUserItemPreference(u, i), 0.0);
115 | }
116 | }
117 | }
118 | }
119 |
--------------------------------------------------------------------------------
/rival-evaluate/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 4.0.0
4 |
5 | net.recommenders.rival
6 | rival
7 | 0.3-SNAPSHOT
8 | ../
9 |
10 | rival-evaluate
11 | jar
12 | RiVal Evaluation
13 |
14 |
15 |
16 | junit
17 | junit
18 |
19 |
20 | net.recommenders.rival
21 | rival-core
22 | ${project.version}
23 |
24 |
25 | org.apache.commons
26 | commons-math3
27 | 3.5
28 |
29 |
30 |
31 |
32 |
33 |
34 | org.apache.maven.plugins
35 | maven-compiler-plugin
36 |
37 |
38 | org.codehaus.mojo
39 | exec-maven-plugin
40 |
41 | net.recommenders.rival.evaluation.strategy.MultipleStrategyRunnerInfile
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
--------------------------------------------------------------------------------
/rival-evaluate/run.sh:
--------------------------------------------------------------------------------
1 | mvn exec:java -e -DpropertyFile=$1
2 |
--------------------------------------------------------------------------------
/rival-evaluate/src/main/java/net/recommenders/rival/evaluation/Pair.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2015 recommenders.net.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package net.recommenders.rival.evaluation;
17 |
18 | /**
19 | * Bean class to store an element of type A and another of type B.
20 | *
21 | * @param The type of the first element in the pair.
22 | * @param The type of the second element in the pair.
23 | *
24 | * @author Alejandro
25 | */
26 | public class Pair {
27 |
28 | /**
29 | * First element.
30 | */
31 | private A first;
32 | /**
33 | * Second element.
34 | */
35 | private B second;
36 |
37 | /**
38 | * Default constructor.
39 | *
40 | * @param firstElement first element to store
41 | * @param secondElement second element to store
42 | */
43 | public Pair(final A firstElement, final B secondElement) {
44 | this.first = firstElement;
45 | this.second = secondElement;
46 | }
47 |
48 | /**
49 | * Gets the first element of the pair.
50 | *
51 | * @return the first element of the pair
52 | */
53 | public A getFirst() {
54 | return first;
55 | }
56 |
57 | /**
58 | * Gets the second element of the pair.
59 | *
60 | * @return the second element of the pair
61 | */
62 | public B getSecond() {
63 | return second;
64 | }
65 | }
66 |
--------------------------------------------------------------------------------
/rival-evaluate/src/main/java/net/recommenders/rival/evaluation/metric/EvaluationMetric.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2015 recommenders.net.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package net.recommenders.rival.evaluation.metric;
17 |
18 | import java.util.Map;
19 |
20 | /**
21 | * An evaluation metric expressing the quality of the evaluated system.
22 | *
23 | * @author Alejandro
24 | *
25 | * @param generic type for users
26 | */
27 | public interface EvaluationMetric {
28 |
29 | /**
30 | * Get the overall value of the metric.
31 | *
32 | * @return The overall value of the metric.
33 | */
34 | double getValue();
35 |
36 | /**
37 | * Get the value of the metric on a per-user basis.
38 | *
39 | * @return Map containing the values per user.
40 | */
41 | Map getValuePerUser();
42 |
43 | /**
44 | * Get the value of the metric for a specific user.
45 | *
46 | * @param u user whose metric value will be computed
47 | *
48 | * @return a value for user u.
49 | */
50 | double getValue(V u);
51 |
52 | /**
53 | * Computes the evaluation metric. This method should be called
54 | * before asking for the values of the metric.
55 | */
56 | void compute();
57 | }
58 |
--------------------------------------------------------------------------------
/rival-evaluate/src/main/java/net/recommenders/rival/evaluation/metric/error/MAE.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2015 recommenders.net.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package net.recommenders.rival.evaluation.metric.error;
17 |
18 | import net.recommenders.rival.core.DataModelIF;
19 | import net.recommenders.rival.evaluation.metric.EvaluationMetric;
20 |
21 | import java.util.List;
22 | import java.util.Map;
23 |
24 | /**
25 | * Mean absolute
26 | * error (MAE) of a list of predicted ratings.
27 | *
28 | * @author Alejandro.
29 | *
30 | * @param - type associated to users' ids
31 | * @param - type associated to items' ids
32 | */
33 | public class MAE extends AbstractErrorMetric implements EvaluationMetric {
34 |
35 | /**
36 | * Default constructor with predictions and groundtruth information.
37 | *
38 | * @param predictions predicted scores for users and items
39 | * @param test groundtruth information for users and items
40 | */
41 | public MAE(final DataModelIF predictions, final DataModelIF test) {
42 | super(predictions, test);
43 | }
44 |
45 | /**
46 | * Constructor where the error strategy can be initialized.
47 | *
48 | * @param predictions predicted scores for users and items
49 | * @param test groundtruth information for users and items
50 | * @param errorStrategy the error strategy
51 | */
52 | public MAE(final DataModelIF predictions, final DataModelIF test, final ErrorStrategy errorStrategy) {
53 | super(predictions, test, errorStrategy);
54 | }
55 |
56 | /**
57 | * Instantiates and computes the MAE value. Prior to running this, there is
58 | * no valid value.
59 | *
60 | */
61 | @Override
62 | public void compute() {
63 | if (!Double.isNaN(getValue())) {
64 | // since the data cannot change, avoid re-doing the calculations
65 | return;
66 | }
67 | iniCompute();
68 |
69 | Map> data = processDataAsPredictedDifferencesToTest();
70 |
71 | int testItems = 0;
72 | for (U testUser : getTest().getUsers()) {
73 | int userItems = 0;
74 | double ume = 0.0;
75 |
76 | if (data.containsKey(testUser)) {
77 | for (double difference : data.get(testUser)) {
78 | ume += Math.abs(difference);
79 | userItems++;
80 | }
81 | }
82 |
83 | testItems += userItems;
84 | setValue(getValue() + ume);
85 | if (userItems == 0) {
86 | ume = Double.NaN;
87 | } else {
88 | ume = ume / userItems;
89 | }
90 | getMetricPerUser().put(testUser, ume);
91 | }
92 | if (testItems == 0) {
93 | setValue(Double.NaN);
94 | } else {
95 | setValue(getValue() / testItems);
96 | }
97 | }
98 |
99 | /**
100 | * {@inheritDoc}
101 | */
102 | @Override
103 | public String toString() {
104 | return "MAE_" + getStrategy();
105 | }
106 | }
107 |
--------------------------------------------------------------------------------
/rival-evaluate/src/main/java/net/recommenders/rival/evaluation/metric/error/RMSE.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2015 recommenders.net.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package net.recommenders.rival.evaluation.metric.error;
17 |
18 | import net.recommenders.rival.core.DataModelIF;
19 | import net.recommenders.rival.evaluation.metric.EvaluationMetric;
20 |
21 | import java.util.List;
22 | import java.util.Map;
23 |
24 | /**
25 | * Root mean square
26 | * error (RMSE) of a list of predicted ratings.
27 | *
28 | * @author Alan.
29 | *
30 | * @param - type associated to users' ids
31 | * @param - type associated to items' ids
32 | */
33 | public class RMSE extends AbstractErrorMetric implements EvaluationMetric {
34 |
35 | /**
36 | * Default constructor with predictions and groundtruth information.
37 | *
38 | * @param predictions predicted scores for users and items
39 | * @param test groundtruth information for users and items
40 | */
41 | public RMSE(final DataModelIF predictions, final DataModelIF test) {
42 | super(predictions, test);
43 | }
44 |
45 | /**
46 | * Constructor where the error strategy can be initialized.
47 | *
48 | * @param predictions predicted scores for users and items
49 | * @param test groundtruth information for users and items
50 | * @param errorStrategy the error strategy
51 | */
52 | public RMSE(final DataModelIF predictions, final DataModelIF test, final ErrorStrategy errorStrategy) {
53 | super(predictions, test, errorStrategy);
54 | }
55 |
56 | /**
57 | * Instantiates and computes the RMSE value. Prior to running this, there is
58 | * no valid value.
59 | *
60 | */
61 | @Override
62 | public void compute() {
63 | if (!Double.isNaN(getValue())) {
64 | // since the data cannot change, avoid re-doing the calculations
65 | return;
66 | }
67 | iniCompute();
68 |
69 | Map> data = processDataAsPredictedDifferencesToTest();
70 | int testItems = 0;
71 | for (U testUser : getTest().getUsers()) {
72 | int userItems = 0;
73 | double umse = 0.0;
74 |
75 | if (data.containsKey(testUser)) {
76 | for (double difference : data.get(testUser)) {
77 | umse += difference * difference;
78 | userItems++;
79 | }
80 | }
81 |
82 | testItems += userItems;
83 | setValue(getValue() + umse);
84 | if (userItems == 0) {
85 | umse = Double.NaN;
86 | } else {
87 | umse = Math.sqrt(umse / userItems);
88 | }
89 | getMetricPerUser().put(testUser, umse);
90 | }
91 | if (testItems == 0) {
92 | setValue(Double.NaN);
93 | } else {
94 | setValue(Math.sqrt(getValue() / testItems));
95 | }
96 | }
97 |
98 | /**
99 | * {@inheritDoc}
100 | */
101 | @Override
102 | public String toString() {
103 | return "RMSE_" + getStrategy();
104 | }
105 | }
106 |
--------------------------------------------------------------------------------
/rival-evaluate/src/main/java/net/recommenders/rival/evaluation/metric/error/package-info.java:
--------------------------------------------------------------------------------
1 | /**
2 | * RiVal Rating Prediction error metrics.
3 | */
4 | package net.recommenders.rival.evaluation.metric.error;
5 |
--------------------------------------------------------------------------------
/rival-evaluate/src/main/java/net/recommenders/rival/evaluation/metric/package-info.java:
--------------------------------------------------------------------------------
1 | /**
2 | * RiVal Evaluation metrics.
3 | */
4 | package net.recommenders.rival.evaluation.metric;
5 |
--------------------------------------------------------------------------------
/rival-evaluate/src/main/java/net/recommenders/rival/evaluation/metric/ranking/package-info.java:
--------------------------------------------------------------------------------
1 | /**
2 | * RiVal Recommendation/Ranking accuracy metrics.
3 | */
4 | package net.recommenders.rival.evaluation.metric.ranking;
5 |
--------------------------------------------------------------------------------
/rival-evaluate/src/main/java/net/recommenders/rival/evaluation/package-info.java:
--------------------------------------------------------------------------------
1 | /**
2 | * RiVal Evaluation classes.
3 | */
4 | package net.recommenders.rival.evaluation;
5 |
--------------------------------------------------------------------------------
/rival-evaluate/src/main/java/net/recommenders/rival/evaluation/parser/TrecEvalParser.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2015 recommenders.net.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package net.recommenders.rival.evaluation.parser;
17 |
18 | import java.io.BufferedReader;
19 | import java.io.File;
20 | import java.io.FileInputStream;
21 | import java.io.IOException;
22 | import java.io.InputStreamReader;
23 | import net.recommenders.rival.core.DataModel;
24 | import net.recommenders.rival.core.DataModelFactory;
25 | import net.recommenders.rival.core.DataModelIF;
26 | import net.recommenders.rival.core.Parser;
27 | import net.recommenders.rival.core.TemporalDataModelIF;
28 |
29 | /**
30 | * A parser based on the format of trec_eval output (no timestamp info).
31 | *
32 | * @author Alejandro
33 | */
34 | public class TrecEvalParser implements Parser {
35 |
36 | /**
37 | * The column index for the user id in the file.
38 | */
39 | public static final int USER_TOK = 0;
40 | /**
41 | * The column index for the item id in the file.
42 | */
43 | public static final int ITEM_TOK = 2;
44 | /**
45 | * The column index for the rating in the file.
46 | */
47 | public static final int RATING_TOK = 4;
48 |
49 | /**
50 | * {@inheritDoc}
51 | */
52 | @Override
53 | public TemporalDataModelIF parseTemporalData(final File f) throws IOException {
54 | return null;
55 | }
56 |
57 | /**
58 | * {@inheritDoc}
59 | */
60 | @Override
61 | public DataModelIF parseData(final File f) throws IOException {
62 | DataModelIF dataset = DataModelFactory.getDefaultModel();
63 |
64 | BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(f), "UTF-8"));
65 | try {
66 | String line = null;
67 | while ((line = br.readLine()) != null) {
68 | parseLine(line, dataset);
69 | }
70 | } finally {
71 | br.close();
72 | }
73 |
74 | return dataset;
75 | }
76 |
77 | /**
78 | * A method that parses a line from the file.
79 | *
80 | * @param line the line to be parsed
81 | * @param dataset the dataset where the information parsed from the line
82 | * will be stored into.
83 | */
84 | private void parseLine(final String line, final DataModelIF dataset) {
85 | String[] toks = line.split("\t");
86 | // user
87 | long userId = Long.parseLong(toks[USER_TOK]);
88 | // item
89 | long itemId = Long.parseLong(toks[ITEM_TOK]);
90 | // preference
91 | double preference = Double.parseDouble(toks[RATING_TOK]);
92 | //////
93 | // update information
94 | //////
95 | dataset.addPreference(userId, itemId, preference);
96 | // no timestamp info
97 | }
98 | }
99 |
--------------------------------------------------------------------------------
/rival-evaluate/src/main/java/net/recommenders/rival/evaluation/parser/package-info.java:
--------------------------------------------------------------------------------
1 | /**
2 | * RiVal Parsers for evaluation purposes.
3 | */
4 | package net.recommenders.rival.evaluation.parser;
5 |
--------------------------------------------------------------------------------
/rival-evaluate/src/main/java/net/recommenders/rival/evaluation/statistics/StandardError.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2015 recommenders.net.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package net.recommenders.rival.evaluation.statistics;
17 |
18 | import java.util.HashSet;
19 | import java.util.Map;
20 | import java.util.Set;
21 | import org.apache.commons.math3.stat.descriptive.SummaryStatistics;
22 |
23 | /**
24 | *
25 | * Class used to compute the standard error of an algorithm with respect to the
26 | * baseline.
27 | *
28 | * @author Alejandro
29 | *
30 | * @param generic type for users
31 | */
32 | public class StandardError {
33 |
34 | /**
35 | * Baseline metric for each dimension (users).
36 | */
37 | private Map baselineMetricPerDimension;
38 | /**
39 | * Test metric for each dimension (users).
40 | */
41 | private Map testMetricPerDimension;
42 |
43 | /**
44 | * Default constructor.
45 | *
46 | * @param theBaselineMetricPerDimension map for the baseline method, one
47 | * value for each user (dimension)
48 | * @param theTestMetricPerDimension map for the test method, one value for
49 | * each user (dimension)
50 | */
51 | public StandardError(final Map theBaselineMetricPerDimension, final Map theTestMetricPerDimension) {
52 | this.baselineMetricPerDimension = theBaselineMetricPerDimension;
53 | this.testMetricPerDimension = theTestMetricPerDimension;
54 | }
55 |
56 | /**
57 | * Implements equation (8.13) from "Elementary Statistics: A Problem Solving
58 | * Approach 4th Edition", Andrew L. Comrey, Howard B. Lee
59 | *
60 | * @return the standard error as the ratio of the standard deviation divided
61 | * by the sqrt(number of users) of the distribution of difference scores.
62 | */
63 | public double getStandardError() {
64 | Set overlap = new HashSet(baselineMetricPerDimension.keySet());
65 | overlap.retainAll(testMetricPerDimension.keySet());
66 |
67 | // paired or matched samples --> analyse distribution of difference scores
68 | SummaryStatistics differences = new SummaryStatistics();
69 | for (V key : overlap) {
70 | double diff = baselineMetricPerDimension.get(key) - testMetricPerDimension.get(key);
71 | differences.addValue(diff);
72 | }
73 |
74 | double e = differences.getStandardDeviation() / Math.sqrt(differences.getN());
75 | return e;
76 | }
77 |
78 | /**
79 | * {@inheritDoc}
80 | */
81 | @Override
82 | public String toString() {
83 | return "StandardError";
84 | }
85 | }
86 |
--------------------------------------------------------------------------------
/rival-evaluate/src/main/java/net/recommenders/rival/evaluation/statistics/StatisticalSignificance.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2015 recommenders.net.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package net.recommenders.rival.evaluation.statistics;
17 |
18 | import java.util.HashSet;
19 | import java.util.Map;
20 | import java.util.Set;
21 | import org.apache.commons.math3.stat.inference.TestUtils;
22 | import org.apache.commons.math3.stat.inference.WilcoxonSignedRankTest;
23 |
24 | /**
25 | *
26 | * Class used to compute statistical significance methods, such as t's Student
27 | * (paired or not) and Wilcoxon.
28 | *
29 | * @author Alejandro
30 | */
31 | public class StatisticalSignificance {
32 |
33 | /**
34 | * Baseline metric for each dimension (users).
35 | */
36 | private Map, Double> baselineMetricPerDimension;
37 | /**
38 | * Test metric for each dimension (users).
39 | */
40 | private Map, Double> testMetricPerDimension;
41 | /**
42 | * Users.
43 | */
44 | private Set> dimensions;
45 |
46 | /**
47 | * Default constructor.
48 | *
49 | * @param theBaselineMetricPerDimension map for the baseline method, one
50 | * value for each user (dimension)
51 | * @param theTestMetricPerDimension map for the test method, one value for
52 | * each user (dimension)
53 | */
54 | public StatisticalSignificance(final Map, Double> theBaselineMetricPerDimension, final Map, Double> theTestMetricPerDimension) {
55 | this.baselineMetricPerDimension = theBaselineMetricPerDimension;
56 | this.testMetricPerDimension = theTestMetricPerDimension;
57 | this.dimensions = new HashSet<>(baselineMetricPerDimension.keySet());
58 | this.dimensions.retainAll(testMetricPerDimension.keySet());
59 | }
60 |
61 | /**
62 | * Gets the p-value according to the requested method.
63 | *
64 | * @param method one of "t", "pairedT", "wilcoxon"
65 | * @return the p-value according to the requested method
66 | */
67 | public double getPValue(final String method) {
68 | double p = Double.NaN;
69 |
70 | if ("t".equals(method)) {
71 | double[] baselineValues = new double[baselineMetricPerDimension.values().size()];
72 | int i = 0;
73 | for (Double d : baselineMetricPerDimension.values()) {
74 | baselineValues[i] = d;
75 | i++;
76 | }
77 |
78 | double[] testValues = new double[testMetricPerDimension.values().size()];
79 | i = 0;
80 | for (Double d : testMetricPerDimension.values()) {
81 | testValues[i] = d;
82 | i++;
83 | }
84 |
85 | p = TestUtils.tTest(baselineValues, testValues);
86 | } else {
87 | double[] baselineValues = new double[dimensions.size()];
88 | int i = 0;
89 | for (Object d : dimensions) {
90 | baselineValues[i] = baselineMetricPerDimension.get(d);
91 | i++;
92 | }
93 |
94 | double[] testValues = new double[dimensions.size()];
95 | i = 0;
96 | for (Object d : dimensions) {
97 | testValues[i] = testMetricPerDimension.get(d);
98 | i++;
99 | }
100 | if ("pairedT".equals(method)) {
101 | p = TestUtils.pairedTTest(baselineValues, testValues);
102 | } else if ("wilcoxon".equals(method)) {
103 | p = new WilcoxonSignedRankTest().wilcoxonSignedRankTest(baselineValues, testValues, false);
104 | }
105 | }
106 | return p;
107 | }
108 |
109 | /**
110 | * {@inheritDoc}
111 | */
112 | @Override
113 | public String toString() {
114 | return "StatisticalSignificance";
115 | }
116 | }
117 |
--------------------------------------------------------------------------------
/rival-evaluate/src/main/java/net/recommenders/rival/evaluation/statistics/package-info.java:
--------------------------------------------------------------------------------
1 | /**
2 | * RiVal Metrics related to statistics measures.
3 | */
4 | package net.recommenders.rival.evaluation.statistics;
5 |
--------------------------------------------------------------------------------
/rival-evaluate/src/main/java/net/recommenders/rival/evaluation/strategy/AllItems.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2015 recommenders.net.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package net.recommenders.rival.evaluation.strategy;
17 |
18 | import java.util.Set;
19 | import net.recommenders.rival.core.DataModelIF;
20 |
21 | /**
22 | * An evaluation strategy where all the items are used as candidates.
23 | *
24 | * @author Alejandro
25 | */
26 | public class AllItems extends AbstractStrategy {
27 |
28 | /**
29 | * Default constructor.
30 | *
31 | * @see
32 | * AbstractStrategy#AbstractStrategy(net.recommenders.rival.core.DataModelIF,
33 | * net.recommenders.rival.core.DataModelIF, double)
34 | *
35 | * @param training The training set.
36 | * @param test The test set.
37 | * @param threshold The relevance threshold.
38 | */
39 | public AllItems(final DataModelIF training, final DataModelIF test, final double threshold) {
40 | super(training, test, threshold);
41 | }
42 |
43 | /**
44 | * {@inheritDoc}
45 | */
46 | @Override
47 | public Set getCandidateItemsToRank(final Long user) {
48 | final Set items = getModelTrainingDifference(getTraining(), user);
49 | items.addAll(getModelTrainingDifference(getTest(), user));
50 | return items;
51 | }
52 |
53 | /**
54 | * {@inheritDoc}
55 | */
56 | @Override
57 | public String toString() {
58 | return "AllItems_" + getThreshold();
59 | }
60 | }
61 |
--------------------------------------------------------------------------------
/rival-evaluate/src/main/java/net/recommenders/rival/evaluation/strategy/EvaluationStrategy.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2015 recommenders.net.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package net.recommenders.rival.evaluation.strategy;
17 |
18 | import java.io.PrintStream;
19 | import java.util.List;
20 | import java.util.Set;
21 | import net.recommenders.rival.evaluation.Pair;
22 |
23 | /**
24 | * An interface for evaluation strategies.
25 | *
26 | * @author Alejandro
27 | *
28 | * @param generic type for users
29 | * @param generic type for items
30 | */
31 | public interface EvaluationStrategy {
32 |
33 | /**
34 | * Enumeration that defines two output formats: a simple one (tab-separated)
35 | * and another compatible with the one used by the treceval program.
36 | */
37 | public enum OUTPUT_FORMAT {
38 |
39 | /**
40 | * Tab-separated format.
41 | */
42 | SIMPLE,
43 | /**
44 | * Format as followed by the trec_eval program.
45 | */
46 | TRECEVAL;
47 | }
48 |
49 | /**
50 | * Get the items to rank.
51 | *
52 | * @param user The user.
53 | * @return The items to rank.
54 | */
55 | Set getCandidateItemsToRank(U user);
56 |
57 | /**
58 | * Print rankings for a user.
59 | *
60 | * @param user The user.
61 | * @param scoredItems The scored items to print.
62 | * @param out Where to print.
63 | * @param format The format of the printer (see {@link OUTPUT_FORMAT}).
64 | */
65 | void printRanking(U user, List> scoredItems, PrintStream out, OUTPUT_FORMAT format);
66 |
67 | /**
68 | * Print the ground truth.
69 | *
70 | * @param user The user.
71 | * @param out Where to print.
72 | * @param format The format of the printer (see {@link OUTPUT_FORMAT}).
73 | */
74 | void printGroundtruth(U user, PrintStream out, OUTPUT_FORMAT format);
75 | }
76 |
--------------------------------------------------------------------------------
/rival-evaluate/src/main/java/net/recommenders/rival/evaluation/strategy/EvaluationStrategyPerItem.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2015 recommenders.net.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package net.recommenders.rival.evaluation.strategy;
17 |
18 | import java.util.Set;
19 |
20 | /**
21 | * An interface for the per-item evaluation strategy.
22 | *
23 | * @author Alejandro
24 | *
25 | * @param generic type for users
26 | * @param generic type for items
27 | */
28 | public interface EvaluationStrategyPerItem {
29 |
30 | /**
31 | * Get the items to rank.
32 | *
33 | * @param user The user.
34 | * @param item The item.
35 | * @return The items to rank.
36 | */
37 | Set getCandidateItemsToRank(U user, I item);
38 | }
39 |
--------------------------------------------------------------------------------
/rival-evaluate/src/main/java/net/recommenders/rival/evaluation/strategy/StrategyIO.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2015 recommenders.net.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package net.recommenders.rival.evaluation.strategy;
17 |
18 | import java.util.ArrayList;
19 | import java.util.List;
20 | import java.util.Map;
21 | import net.recommenders.rival.evaluation.Pair;
22 |
23 | /**
24 | * Methods related to input/output of strategies.
25 | *
26 | * @author Alan.
27 | */
28 | public final class StrategyIO {
29 |
30 | /**
31 | * Utility classes should not have a public or default constructor.
32 | */
33 | private StrategyIO() {
34 | }
35 |
36 | /**
37 | * Read a file from the recommended items file.
38 | *
39 | * @param line The line.
40 | * @param mapUserRecommendations The recommendations for the users where
41 | * information will be stored into.
42 | */
43 | public static void readLine(final String line, final Map>> mapUserRecommendations) {
44 | String[] toks = line.split("\t");
45 | // mymedialite format: user \t [item:score,item:score,...]
46 | if (line.contains(":") && line.contains(",")) {
47 | Long user = Long.parseLong(toks[0]);
48 | String items = toks[1].replace("[", "").replace("]", "");
49 | for (String pair : items.split(",")) {
50 | String[] pairToks = pair.split(":");
51 | Long item = Long.parseLong(pairToks[0]);
52 | Double score = Double.parseDouble(pairToks[1]);
53 | List> userRec = mapUserRecommendations.get(user);
54 | if (userRec == null) {
55 | userRec = new ArrayList>();
56 | mapUserRecommendations.put(user, userRec);
57 | }
58 | userRec.add(new Pair(item, score));
59 | }
60 | } else {
61 | Long user = Long.parseLong(toks[0]);
62 | Long item = Long.parseLong(toks[1]);
63 | Double score = Double.parseDouble(toks[2]);
64 | List> userRec = mapUserRecommendations.get(user);
65 | if (userRec == null) {
66 | userRec = new ArrayList>();
67 | mapUserRecommendations.put(user, userRec);
68 | }
69 | userRec.add(new Pair(item, score));
70 | }
71 | }
72 | }
73 |
--------------------------------------------------------------------------------
/rival-evaluate/src/main/java/net/recommenders/rival/evaluation/strategy/TestItems.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2015 recommenders.net.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package net.recommenders.rival.evaluation.strategy;
17 |
18 | import java.util.Set;
19 | import net.recommenders.rival.core.DataModelIF;
20 |
21 | /**
22 | * An evaluation strategy where only the test items are used as candidates.
23 | *
24 | * @author Alejandro
25 | */
26 | public class TestItems extends AbstractStrategy {
27 |
28 | /**
29 | * Default constructor.
30 | *
31 | * @see
32 | * AbstractStrategy#AbstractStrategy(net.recommenders.rival.core.DataModelIF,
33 | * net.recommenders.rival.core.DataModelIF, double)
34 | *
35 | * @param training The training set.
36 | * @param test The test set.
37 | * @param threshold The relevance threshold.
38 | */
39 | public TestItems(final DataModelIF training, final DataModelIF test, final double threshold) {
40 | super(training, test, threshold);
41 | }
42 |
43 | /**
44 | * {@inheritDoc}
45 | */
46 | @Override
47 | public Set getCandidateItemsToRank(final Long user) {
48 | return getModelTrainingDifference(getTest(), user);
49 | }
50 |
51 | /**
52 | * {@inheritDoc}
53 | */
54 | @Override
55 | public String toString() {
56 | return "TestItems_" + getThreshold();
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/rival-evaluate/src/main/java/net/recommenders/rival/evaluation/strategy/TrainItems.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2015 recommenders.net.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package net.recommenders.rival.evaluation.strategy;
17 |
18 | import java.util.Set;
19 | import net.recommenders.rival.core.DataModelIF;
20 |
21 | /**
22 | * An evaluation strategy where only the items in training are used as
23 | * candidates.
24 | *
25 | * @author Alejandro
26 | */
27 | public class TrainItems extends AbstractStrategy {
28 |
29 | /**
30 | * Default constructor.
31 | *
32 | * @see
33 | * AbstractStrategy#AbstractStrategy(net.recommenders.rival.core.DataModelIF,
34 | * net.recommenders.rival.core.DataModelIF, double)
35 | *
36 | * @param training The training set.
37 | * @param test The test set.
38 | * @param threshold The relevance threshold.
39 | */
40 | public TrainItems(final DataModelIF training, final DataModelIF test, final double threshold) {
41 | super(training, test, threshold);
42 | }
43 |
44 | /**
45 | * {@inheritDoc}
46 | */
47 | @Override
48 | public Set getCandidateItemsToRank(final Long user) {
49 | return getModelTrainingDifference(getTraining(), user);
50 | }
51 |
52 | /**
53 | * {@inheritDoc}
54 | */
55 | @Override
56 | public String toString() {
57 | return "TrainItems_" + getThreshold();
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/rival-evaluate/src/main/java/net/recommenders/rival/evaluation/strategy/UserTest.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2015 recommenders.net.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package net.recommenders.rival.evaluation.strategy;
17 |
18 | import java.util.HashSet;
19 | import java.util.Set;
20 | import net.recommenders.rival.core.DataModelIF;
21 |
22 | /**
23 | * An evaluation strategy where only the items in the user's test are used as
24 | * candidates.
25 | *
26 | * @author Alejandro
27 | */
28 | public class UserTest extends AbstractStrategy {
29 |
30 | /**
31 | * Default constructor.
32 | *
33 | * @see
34 | * AbstractStrategy#AbstractStrategy(net.recommenders.rival.core.DataModelIF,
35 | * net.recommenders.rival.core.DataModelIF, double)
36 | *
37 | * @param training The training set.
38 | * @param test The test set.
39 | * @param threshold The relevance threshold.
40 | */
41 | public UserTest(final DataModelIF training, final DataModelIF test, final double threshold) {
42 | super(training, test, threshold);
43 | }
44 |
45 | /**
46 | * {@inheritDoc}
47 | */
48 | @Override
49 | public Set getCandidateItemsToRank(final Long user) {
50 | Set items = new HashSet<>();
51 | for (Long i : getTest().getUserItems(user)) {
52 | items.add(i);
53 | }
54 | return items;
55 | }
56 |
57 | /**
58 | * {@inheritDoc}
59 | */
60 | @Override
61 | public String toString() {
62 | return "UserTest_" + getThreshold();
63 | }
64 | }
65 |
--------------------------------------------------------------------------------
/rival-evaluate/src/main/java/net/recommenders/rival/evaluation/strategy/package-info.java:
--------------------------------------------------------------------------------
1 | /**
2 | * RiVal evaluation strategies.
3 | */
4 | package net.recommenders.rival.evaluation.strategy;
5 |
--------------------------------------------------------------------------------
/rival-evaluate/src/main/resources/allitems.strategy.properties:
--------------------------------------------------------------------------------
1 | split.training.file=
2 | split.test.file=
3 | recommendation.file=
4 | output.format=TRECEVAL
5 | output.file.ranking=
6 | output.file.groundtruth=
7 | strategy.class=net.recommenders.rival.evaluation.strategy.AllItems
8 | strategy.relevance.threshold=4
9 |
--------------------------------------------------------------------------------
/rival-evaluate/src/main/resources/metric.properties:
--------------------------------------------------------------------------------
1 | evaluation.pred.file=
2 | evaluation.pred.format=TRECEVAL
3 | evaluation.test.file=
4 | evaluation.output.overwrite=false
5 | evaluation.output.append=true
6 | evaluation.output.file=
7 | evaluation.classes=net.recommenders.rival.evaluation.metric.error.MAE,net.recommenders.rival.evaluation.metric.error.RMSE,net.recommenders.rival.evaluation.metric.ranking.MAP,net.recommenders.rival.evaluation.metric.ranking.NDCG,net.recommenders.rival.evaluation.metric.ranking.Precision,net.recommenders.rival.evaluation.metric.ranking.Recall
8 | evaluation.ndcg.type=exp
9 | evaluation.relevance.threshold=5
10 | evaluation.ranking.cutoffs=1,5,10,50
11 | evaluation.error.strategy=NOT_CONSIDER_NAN
12 | evaluation.peruser=false
13 |
--------------------------------------------------------------------------------
/rival-evaluate/src/main/resources/relplusn.strategy.properties:
--------------------------------------------------------------------------------
1 | split.training.file=
2 | split.test.file=
3 | recommendation.file=
4 | output.format=TRECEVAL
5 | output.file.ranking=
6 | output.file.groundtruth=
7 | strategy.class=net.recommenders.rival.evaluation.strategy.RelPlusN
8 | strategy.relevance.threshold=5
9 | strategy.relplusn.N=100
10 | strategy.relplusn.seed=2014
11 |
--------------------------------------------------------------------------------
/rival-evaluate/src/main/resources/statistics.properties:
--------------------------------------------------------------------------------
1 | algorithm.baseline.file=
2 | algorithm.methods.files=
3 | input.format.statistics=default
4 | output.overwrite.statistics=false
5 | output.file.statistics=
6 | statistics.functions=confidence_interval,effect_size_d,effect_size_dLS,effect_size_pairedT,standard_error,statistical_significance_t,statistical_significance_pairedT,statistical_significance_wilcoxon
7 | statistics.alpha=0.05
8 | statistics.users_to_avoid=all
9 |
--------------------------------------------------------------------------------
/rival-evaluate/src/main/resources/strategy.properties:
--------------------------------------------------------------------------------
1 | split.folder=
2 | split.training.suffix=
3 | split.test.suffix=
4 | recommendation.folder=
5 | recommendation.suffix=
6 | output.format=TRECEVAL
7 | output.overwrite=false
8 | output.ranking.folder=
9 | output.groundtruth.folder=
10 | strategy.classes=net.recommenders.rival.evaluation.strategy.RelPlusN,net.recommenders.rival.evaluation.strategy.TestItems,net.recommenders.rival.evaluation.strategy.AllItems,net.recommenders.rival.evaluation.strategy.TrainItems,net.recommenders.rival.evaluation.strategy.UserTest
11 | strategy.relevance.thresholds=5
12 | strategy.relplusn.N=100
13 | strategy.relplusn.seed=2014
14 |
--------------------------------------------------------------------------------
/rival-evaluate/src/main/resources/testitems.strategy.properties:
--------------------------------------------------------------------------------
1 | split.training.file=
2 | split.test.file=
3 | recommendation.file=
4 | output.format=TRECEVAL
5 | output.file.ranking=
6 | output.file.groundtruth=
7 | strategy.class=net.recommenders.rival.evaluation.strategy.TestItems
8 | strategy.relevance.threshold=4
9 |
--------------------------------------------------------------------------------
/rival-evaluate/src/main/resources/trainitems.strategy.properties:
--------------------------------------------------------------------------------
1 | split.training.file=
2 | split.test.file=
3 | recommendation.file=
4 | output.format=TRECEVAL
5 | output.file.ranking=
6 | output.file.groundtruth=
7 | strategy.class=net.recommenders.rival.evaluation.strategy.TrainItems
8 | strategy.relevance.threshold=4
9 |
--------------------------------------------------------------------------------
/rival-evaluate/src/main/resources/usertest.strategy.properties:
--------------------------------------------------------------------------------
1 | split.training.file=
2 | split.test.file=
3 | recommendation.file=
4 | output.format=TRECEVAL
5 | output.file.ranking=
6 | output.file.groundtruth=
7 | strategy.class=net.recommenders.rival.evaluation.strategy.UserTest
8 | strategy.relevance.threshold=4
9 |
--------------------------------------------------------------------------------
/rival-evaluate/src/test/java/net/recommenders/rival/evaluation/metric/MAETest.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2015 recommenders.net.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package net.recommenders.rival.evaluation.metric;
17 |
18 | import net.recommenders.rival.core.DataModelFactory;
19 | import net.recommenders.rival.core.DataModelIF;
20 | import net.recommenders.rival.evaluation.metric.error.MAE;
21 | import org.junit.Test;
22 | import org.junit.runner.RunWith;
23 | import org.junit.runners.JUnit4;
24 |
25 | import java.util.Map;
26 |
27 | import static org.junit.Assert.assertEquals;
28 |
29 | /**
30 | * Test for {@link MAE}.
31 | *
32 | * @author Alan.
33 | */
34 | @RunWith(JUnit4.class)
35 | public class MAETest {
36 |
37 | @Test
38 | public void testSameGroundtruthAsPredictions() {
39 | DataModelIF predictions = DataModelFactory.getDefaultModel();
40 | DataModelIF test = DataModelFactory.getDefaultModel();
41 | for (int i = 0; i < 5; i++) {
42 | for (int j = 0; j < 10; j++) {
43 | test.addPreference((long) i, (long) j, (double) i * j);
44 | predictions.addPreference((long) i, (long) j, (double) i * j);
45 | }
46 | }
47 | MAE mae = new MAE(predictions, test);
48 |
49 | mae.compute();
50 |
51 | assertEquals(0.0, mae.getValue(), 0.0);
52 |
53 | Map maePerUser = mae.getValuePerUser();
54 | for (Map.Entry e : maePerUser.entrySet()) {
55 | double value = e.getValue();
56 | assertEquals(0.0, value, 0.0);
57 | }
58 | }
59 | }
--------------------------------------------------------------------------------
/rival-evaluate/src/test/java/net/recommenders/rival/evaluation/metric/MAPTest.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2015 recommenders.net.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package net.recommenders.rival.evaluation.metric;
17 |
18 | import net.recommenders.rival.core.DataModel;
19 | import net.recommenders.rival.evaluation.metric.ranking.MAP;
20 | import org.junit.Test;
21 | import org.junit.runner.RunWith;
22 | import org.junit.runners.JUnit4;
23 |
24 | import java.util.Map;
25 | import net.recommenders.rival.core.DataModelFactory;
26 | import net.recommenders.rival.core.DataModelIF;
27 |
28 | import static org.junit.Assert.assertEquals;
29 |
30 | /**
31 | * Tests for {@link MAP}.
32 | *
33 | * @author Alan.
34 | */
35 | @RunWith(JUnit4.class)
36 | public class MAPTest {
37 |
38 | @Test
39 | public void testSameGroundtruthAsPredictions() {
40 | DataModelIF predictions = DataModelFactory.getDefaultModel();
41 | DataModelIF test = DataModelFactory.getDefaultModel();
42 | int nUsers = 20;
43 | int nItems = 15;
44 | for (long i = 1L; i < nUsers + 1; i++) {
45 | for (long j = 1L; j < nItems + 1; j++) {
46 | test.addPreference(i, j, i * j % 5 + 1.0);
47 | predictions.addPreference(i, j, i * j % 5 + 1.0);
48 | }
49 | }
50 | MAP map = new MAP(predictions, test, 1.0, new int[]{1, 5, 10, 20});
51 |
52 | map.compute();
53 |
54 | assertEquals(1.0, map.getValue(), 0.0);
55 | assertEquals(1.0 / nItems, map.getValueAt(1), 0.0001);
56 | assertEquals(1.0 / nItems * 5, map.getValueAt(5), 0.0001);
57 | assertEquals(1.0 / nItems * 10, map.getValueAt(10), 0.0001);
58 |
59 | Map mapPerUser = map.getValuePerUser();
60 | for (Map.Entry e : mapPerUser.entrySet()) {
61 | long user = e.getKey();
62 | double value = e.getValue();
63 | assertEquals(1.0, value, 0.0);
64 | }
65 | }
66 |
67 | @Test
68 | public void testOneUserTrecevalStrategySingleRelevance() {
69 | // groundtruth: ? 0 1 1
70 | // predictions: 3 4 5 1
71 | DataModelIF test = DataModelFactory.getDefaultModel();
72 | DataModelIF predictions = DataModelFactory.getDefaultModel();
73 | test.addPreference(1L, 2L, 0.0);
74 | test.addPreference(1L, 3L, 1.0);
75 | test.addPreference(1L, 4L, 1.0);
76 | predictions.addPreference(1L, 1L, 3.0);
77 | predictions.addPreference(1L, 2L, 4.0);
78 | predictions.addPreference(1L, 3L, 5.0);
79 | predictions.addPreference(1L, 4L, 1.0);
80 |
81 | MAP map = new MAP(predictions, test, 1.0, new int[]{1, 2, 3, 4, 5});
82 |
83 | map.compute();
84 |
85 | assertEquals(0.75, map.getValue(), 0.001);
86 | assertEquals(0.5, map.getValueAt(1), 0.001);
87 | assertEquals(0.5, map.getValueAt(2), 0.001);
88 | assertEquals(0.5, map.getValueAt(3), 0.001);
89 | assertEquals(0.75, map.getValueAt(4), 0.001);
90 | assertEquals(0.75, map.getValueAt(5), 0.001);
91 |
92 | Map mapPerUser = map.getValuePerUser();
93 | for (Map.Entry e : mapPerUser.entrySet()) {
94 | long user = e.getKey();
95 | double value = e.getValue();
96 | assertEquals(0.75, value, 0.001);
97 | }
98 | }
99 |
100 | @Test
101 | public void testOneUserTrecevalStrategyMultipleRelevance() {
102 | // groundtruth: ? 0 1 2
103 | // predictions: 3 4 5 1
104 | DataModelIF test = DataModelFactory.getDefaultModel();
105 | DataModelIF predictions =DataModelFactory.getDefaultModel();
106 | test.addPreference(1L, 2L, 0.0);
107 | test.addPreference(1L, 3L, 1.0);
108 | test.addPreference(1L, 4L, 2.0);
109 | predictions.addPreference(1L, 1L, 3.0);
110 | predictions.addPreference(1L, 2L, 4.0);
111 | predictions.addPreference(1L, 3L, 5.0);
112 | predictions.addPreference(1L, 4L, 1.0);
113 |
114 | MAP map = new MAP(predictions, test, 1.0, new int[]{1, 2, 3, 4, 5});
115 |
116 | map.compute();
117 |
118 | assertEquals(0.75, map.getValue(), 0.001);
119 | assertEquals(0.5, map.getValueAt(1), 0.001);
120 | assertEquals(0.5, map.getValueAt(2), 0.001);
121 | assertEquals(0.5, map.getValueAt(3), 0.001);
122 | assertEquals(0.75, map.getValueAt(4), 0.001);
123 | assertEquals(0.75, map.getValueAt(5), 0.001);
124 |
125 | Map mapPerUser = map.getValuePerUser();
126 | for (Map.Entry e : mapPerUser.entrySet()) {
127 | long user = e.getKey();
128 | double value = e.getValue();
129 | assertEquals(0.75, value, 0.001);
130 | }
131 | }
132 | }
133 |
--------------------------------------------------------------------------------
/rival-evaluate/src/test/java/net/recommenders/rival/evaluation/metric/PopularityStratifiedRecallTest.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2015 recommenders.net.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package net.recommenders.rival.evaluation.metric;
17 |
18 | import java.util.HashMap;
19 | import net.recommenders.rival.core.DataModelIF;
20 | import org.junit.Test;
21 | import org.junit.runner.RunWith;
22 | import org.junit.runners.JUnit4;
23 |
24 | import java.util.Map;
25 | import net.recommenders.rival.core.DataModelFactory;
26 | import net.recommenders.rival.evaluation.metric.ranking.PopularityStratifiedRecall;
27 |
28 | import static org.junit.Assert.assertEquals;
29 |
30 | /**
31 | * Test for {@link PopularityStratifiedRecall}.
32 | *
33 | * @author Alejandro.
34 | */
35 | @RunWith(JUnit4.class)
36 | public class PopularityStratifiedRecallTest {
37 |
38 | @Test
39 | public void testSameGroundtruthAsPredictions() {
40 | DataModelIF predictions = DataModelFactory.getDefaultModel();
41 | DataModelIF test = DataModelFactory.getDefaultModel();
42 | int nUsers = 20;
43 | int nItems = 15;
44 | for (long i = 1L; i < nUsers + 1; i++) {
45 | for (long j = 1L; j < nItems + 1; j++) {
46 | test.addPreference(i, j, i * j % 5 + 1.0);
47 | predictions.addPreference(i, j, i * j % 5 + 1.0);
48 | }
49 | }
50 | Map observedItemRelevance = new HashMap();
51 | for (long j = 1L; j < nItems + 1; j++) {
52 | observedItemRelevance.put(j, Long.valueOf(j).intValue());
53 | }
54 |
55 | double gamma = 0.0;
56 | PopularityStratifiedRecall recall = new PopularityStratifiedRecall(predictions, test, 1.0, new int[]{5, 10, 20}, gamma, observedItemRelevance);
57 |
58 | recall.compute();
59 |
60 | assertEquals(1.0, recall.getValue(), 0.0);
61 | // assertEquals(, recall.getValueAt(5), 0.0001);
62 | // assertEquals(, recall.getValueAt(10), 0.0001);
63 |
64 | Map recallPerUser = recall.getValuePerUser();
65 | for (Map.Entry e : recallPerUser.entrySet()) {
66 | long user = e.getKey();
67 | double value = e.getValue();
68 | assertEquals(1.0, value, 0.0);
69 | }
70 | }
71 | }
72 |
--------------------------------------------------------------------------------
/rival-evaluate/src/test/java/net/recommenders/rival/evaluation/metric/RMSETest.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2015 recommenders.net.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package net.recommenders.rival.evaluation.metric;
17 |
18 | import net.recommenders.rival.core.DataModelIF;
19 | import net.recommenders.rival.evaluation.metric.error.AbstractErrorMetric;
20 | import net.recommenders.rival.evaluation.metric.error.RMSE;
21 | import org.junit.Test;
22 | import org.junit.runner.RunWith;
23 | import org.junit.runners.JUnit4;
24 |
25 | import java.util.Map;
26 | import net.recommenders.rival.core.DataModelFactory;
27 |
28 | import static org.junit.Assert.assertEquals;
29 | import static org.junit.Assert.assertNotNull;
30 |
31 | /**
32 | * Test for {@link RMSE}.
33 | *
34 | * @author Alan.
35 | */
36 | @RunWith(JUnit4.class)
37 | public class RMSETest {
38 |
39 |
40 | @Test
41 | public void testSameGroundtruthAsPredictions() {
42 | DataModelIF predictions = DataModelFactory.getDefaultModel();
43 | DataModelIF test = DataModelFactory.getDefaultModel();
44 | for (int i = 0; i < 5; i++) {
45 | for (int j = 0; j < 10; j++) {
46 | test.addPreference((long) i, (long) j, (double) i * j);
47 | predictions.addPreference((long) i, (long) j, (double) i * j);
48 | }
49 | }
50 | RMSE rmse = new RMSE(predictions, test);
51 |
52 | RMSE rmseStrat = new RMSE(predictions, test, AbstractErrorMetric.ErrorStrategy.CONSIDER_EVERYTHING);
53 | assertNotNull(rmseStrat);
54 |
55 | assertEquals("RMSE_CONSIDER_EVERYTHING", rmseStrat.toString());
56 |
57 | rmse.compute();
58 |
59 | assertEquals(0.0, rmse.getValue(), 0.0);
60 |
61 | Map rmsePerUser = rmse.getValuePerUser();
62 | for (Map.Entry e : rmsePerUser.entrySet()) {
63 | double value = e.getValue();
64 | assertEquals(0.0, value, 0.0);
65 | }
66 | }
67 | }
--------------------------------------------------------------------------------
/rival-evaluate/src/test/java/net/recommenders/rival/evaluation/metric/RecallTest.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2015 recommenders.net.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package net.recommenders.rival.evaluation.metric;
17 |
18 | import net.recommenders.rival.core.DataModelIF;
19 | import net.recommenders.rival.evaluation.metric.ranking.Recall;
20 | import org.junit.Test;
21 | import org.junit.runner.RunWith;
22 | import org.junit.runners.JUnit4;
23 |
24 | import java.util.Map;
25 | import net.recommenders.rival.core.DataModelFactory;
26 |
27 | import static org.junit.Assert.assertEquals;
28 |
29 | /**
30 | * Tests for {@link Recall}.
31 | *
32 | * @author Alan.
33 | */
34 | @RunWith(JUnit4.class)
35 | public class RecallTest {
36 |
37 | @Test
38 | public void testSameGroundtruthAsPredictions() {
39 | DataModelIF predictions = DataModelFactory.getDefaultModel();
40 | DataModelIF test = DataModelFactory.getDefaultModel();
41 | int nUsers = 20;
42 | int nItems = 15;
43 | for (long i = 1L; i < nUsers + 1; i++) {
44 | for (long j = 1L; j < nItems + 1; j++) {
45 | test.addPreference(i, j, i * j % 5 + 1.0);
46 | predictions.addPreference(i, j, i * j % 5 + 1.0);
47 | }
48 | }
49 | Recall recall = new Recall(predictions, test, 1.0, new int[]{5, 10, 20});
50 |
51 | recall.compute();
52 |
53 | assertEquals(1.0, recall.getValue(), 0.0);
54 | assertEquals(5.0 / nItems, recall.getValueAt(5), 0.0001);
55 | assertEquals(10.0 / nItems, recall.getValueAt(10), 0.0001);
56 |
57 | Map recallPerUser = recall.getValuePerUser();
58 | for (Map.Entry e : recallPerUser.entrySet()) {
59 | long user = e.getKey();
60 | double value = e.getValue();
61 | assertEquals(1.0, value, 0.0);
62 | }
63 | }
64 |
65 | @Test
66 | public void testOneUserTrecevalStrategySingleRelevance() {
67 | // groundtruth: ? 0 1 1
68 | // predictions: 3 4 5 1
69 | DataModelIF test = DataModelFactory.getDefaultModel();
70 | DataModelIF predictions = DataModelFactory.getDefaultModel();
71 | test.addPreference(1L, 2L, 0.0);
72 | test.addPreference(1L, 3L, 1.0);
73 | test.addPreference(1L, 4L, 1.0);
74 | predictions.addPreference(1L, 1L, 3.0);
75 | predictions.addPreference(1L, 2L, 4.0);
76 | predictions.addPreference(1L, 3L, 5.0);
77 | predictions.addPreference(1L, 4L, 1.0);
78 |
79 | Recall recall = new Recall(predictions, test, 1.0, new int[]{1, 2, 3, 4, 5});
80 |
81 | recall.compute();
82 |
83 | assertEquals(1.0, recall.getValue(), 0.001);
84 | assertEquals(0.5, recall.getValueAt(1), 0.001);
85 | assertEquals(0.5, recall.getValueAt(2), 0.001);
86 | assertEquals(0.5, recall.getValueAt(3), 0.001);
87 | assertEquals(1.0, recall.getValueAt(4), 0.001);
88 | assertEquals(1.0, recall.getValueAt(5), 0.001);
89 |
90 | Map recallPerUser = recall.getValuePerUser();
91 | for (Map.Entry e : recallPerUser.entrySet()) {
92 | long user = e.getKey();
93 | double value = e.getValue();
94 | assertEquals(1.0, value, 0.001);
95 | }
96 | }
97 |
98 | @Test
99 | public void testOneUserTrecevalStrategyMultipleRelevance() {
100 | // groundtruth: ? 0 1 2
101 | // predictions: 3 4 5 1
102 | DataModelIF test = DataModelFactory.getDefaultModel();
103 | DataModelIF predictions = DataModelFactory.getDefaultModel();
104 | test.addPreference(1L, 2L, 0.0);
105 | test.addPreference(1L, 3L, 1.0);
106 | test.addPreference(1L, 4L, 2.0);
107 | predictions.addPreference(1L, 1L, 3.0);
108 | predictions.addPreference(1L, 2L, 4.0);
109 | predictions.addPreference(1L, 3L, 5.0);
110 | predictions.addPreference(1L, 4L, 1.0);
111 |
112 | Recall recall = new Recall(predictions, test, 1.0, new int[]{1, 2, 3, 4, 5});
113 |
114 | recall.compute();
115 |
116 | assertEquals(1.0, recall.getValue(), 0.001);
117 | assertEquals(0.5, recall.getValueAt(1), 0.001);
118 | assertEquals(0.5, recall.getValueAt(2), 0.001);
119 | assertEquals(0.5, recall.getValueAt(3), 0.001);
120 | assertEquals(1.0, recall.getValueAt(4), 0.001);
121 | assertEquals(1.0, recall.getValueAt(5), 0.001);
122 |
123 | Map recallPerUser = recall.getValuePerUser();
124 | for (Map.Entry e : recallPerUser.entrySet()) {
125 | long user = e.getKey();
126 | double value = e.getValue();
127 | assertEquals(1.0, value, 0.001);
128 | }
129 | }
130 | }
131 |
--------------------------------------------------------------------------------
/rival-examples/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | rival
5 | net.recommenders.rival
6 | 0.3-SNAPSHOT
7 |
8 | 4.0.0
9 |
10 | rival-examples
11 | jar
12 | RiVal Examples
13 |
14 |
15 |
16 | net.recommenders.rival
17 | rival-core
18 | ${project.version}
19 |
20 |
21 | net.recommenders.rival
22 | rival-split
23 | ${project.version}
24 |
25 |
26 | net.recommenders.rival
27 | rival-recommend
28 | ${project.version}
29 |
30 |
31 | net.recommenders.rival
32 | rival-evaluate
33 | ${project.version}
34 |
35 |
36 |
37 | org.apache.mahout
38 | mahout-core
39 | ${mahout.version}
40 |
41 |
42 | junit
43 | junit
44 | test
45 |
46 |
47 | commons-io
48 | commons-io
49 | 2.4
50 |
51 |
52 | net.lingala.zip4j
53 | zip4j
54 | 1.3.2
55 |
56 |
57 |
58 |
59 |
60 |
61 | org.apache.maven.plugins
62 | maven-compiler-plugin
63 |
64 |
65 | org.codehaus.mojo
66 | exec-maven-plugin
67 |
68 | net.recommenders.rival.examples.movietweetings.RandomMahoutIBRecommenderEvaluator
69 |
70 |
71 |
72 |
73 |
--------------------------------------------------------------------------------
/rival-examples/src/main/java/net/recommenders/rival/examples/DataDownloader.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2015 recommenders.net.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package net.recommenders.rival.examples;
17 |
18 | import java.io.File;
19 | import java.io.IOException;
20 | import java.net.MalformedURLException;
21 | import java.net.URL;
22 | import net.lingala.zip4j.core.ZipFile;
23 | import net.lingala.zip4j.exception.ZipException;
24 | import org.apache.commons.io.FileUtils;
25 |
26 | /**
27 | * Class used to download a file and unzips it.
28 | *
29 | * @author Alan.
30 | */
31 | public class DataDownloader {
32 |
33 | /**
34 | * The URL.
35 | */
36 | private String url;
37 | /**
38 | * The folder where the file will be unzipped it.
39 | */
40 | private String folder;
41 |
42 | /**
43 | * Default constructor.
44 | *
45 | * @param theUrl the URL from where the file will be downloaded
46 | * @param theFolder the folder where the file will be uncompressed
47 | */
48 | public DataDownloader(final String theUrl, final String theFolder) {
49 | this.url = theUrl;
50 | this.folder = theFolder;
51 | }
52 |
53 | /**
54 | * Main method.
55 | *
56 | * @param args argument (not used)
57 | */
58 | public static void main(final String[] args) {
59 | String url = "http://files.grouplens.org/datasets/movielens/ml-100k.zip";
60 | String folder = "data3/ml-100k";
61 | DataDownloader dd = new DataDownloader(url, folder);
62 | dd.downloadAndUnzip();
63 | }
64 |
65 | /**
66 | * Downloads the file from the provided url.
67 | */
68 | public void download() {
69 | URL dataURL = null;
70 | String fileName = folder + "/" + url.substring(url.lastIndexOf("/") + 1);
71 | if (new File(fileName).exists()) {
72 | return;
73 | }
74 | try {
75 | dataURL = new URL(url);
76 | } catch (MalformedURLException e) {
77 | e.printStackTrace();
78 | }
79 |
80 | File downloadedData = new File(fileName);
81 | try {
82 | assert dataURL != null;
83 | FileUtils.copyURLToFile(dataURL, downloadedData);
84 | } catch (IOException e) {
85 | e.printStackTrace();
86 | }
87 | }
88 |
89 | /**
90 | * Downloads the file from the provided url and uncompresses it to the given
91 | * folder.
92 | */
93 | public void downloadAndUnzip() {
94 | URL dataURL = null;
95 | String fileName = folder + "/" + url.substring(url.lastIndexOf("/") + 1);
96 | File compressedData = new File(fileName);
97 | if (!new File(fileName).exists()) {
98 | try {
99 | dataURL = new URL(url);
100 | } catch (MalformedURLException e) {
101 | e.printStackTrace();
102 | }
103 | try {
104 | assert dataURL != null;
105 | FileUtils.copyURLToFile(dataURL, compressedData);
106 | } catch (IOException e) {
107 | e.printStackTrace();
108 | }
109 | }
110 | try {
111 | ZipFile zipFile = new ZipFile(compressedData);
112 | File dataFolder = new File(folder);
113 | zipFile.extractAll(dataFolder.getCanonicalPath());
114 | } catch (ZipException | IOException e) {
115 | e.printStackTrace();
116 | }
117 | }
118 | }
119 |
--------------------------------------------------------------------------------
/rival-examples/src/main/java/net/recommenders/rival/examples/mdp/EvaluationMetrics.java:
--------------------------------------------------------------------------------
1 | package net.recommenders.rival.examples.mdp;
2 |
3 | import java.util.HashMap;
4 | import java.util.Map;
5 |
6 | public class EvaluationMetrics {
7 |
8 | private Double rmse;
9 | private Double mae;
10 | private Double precision;
11 | private Double recall;
12 | private Double ndcg;
13 |
14 | private Map precisionAtK;
15 | private Map recallAtK;
16 | private Map ndcgAtK;
17 |
18 | public Double getRmse() {
19 | return rmse;
20 | }
21 |
22 | public Double getMae() {
23 | return mae;
24 | }
25 |
26 | public Double getPrecision() {
27 | return precision;
28 | }
29 |
30 | public Double getRecall() {
31 | return recall;
32 | }
33 |
34 | public Double getNdcg() {
35 | return ndcg;
36 | }
37 |
38 | public Double getPrecisionAtK(int cutoff) {
39 | if (precisionAtK.containsKey(cutoff))
40 | return precisionAtK.get(cutoff);
41 | return Double.NaN;
42 | }
43 |
44 | public Double getRecallAtK(int cutoff) {
45 | if (recallAtK.containsKey(cutoff))
46 | return recallAtK.get(cutoff);
47 | return Double.NaN;
48 | }
49 |
50 | public Double getNdcgAtK(int cutoff) {
51 | if (ndcgAtK.containsKey(cutoff))
52 | return ndcgAtK.get(cutoff);
53 | return Double.NaN;
54 | }
55 |
56 | public EvaluationMetrics() {
57 | this.rmse = 0d;
58 | this.mae = 0d;
59 | this.precision = 0d;
60 | this.recall = 0d;
61 | this.ndcg = 0d;
62 | this.precisionAtK = new HashMap<>();
63 | this.recallAtK = new HashMap<>();
64 | this.ndcgAtK = new HashMap<>();
65 | }
66 |
67 | public void setRMSE(Double rmse) {
68 | this.rmse = rmse;
69 | }
70 |
71 | public void setMAE(Double mae) {
72 | this.mae = mae;
73 | }
74 |
75 | public void setPrecisionAtK(int cutoff, Double precision) {
76 | this.precisionAtK.put(cutoff, precision);
77 | }
78 |
79 | public void setRecallAtK(int cutoff, Double recall) {
80 | this.recallAtK.put(cutoff, recall);
81 | }
82 |
83 | public void setNDCGAtK(int cutoff, Double ndcg) {
84 | this.ndcgAtK.put(cutoff, ndcg);
85 | }
86 | }
87 |
--------------------------------------------------------------------------------
/rival-examples/src/main/java/net/recommenders/rival/examples/mdp/MahoutItemBasedCFRecSysEvaluator.java:
--------------------------------------------------------------------------------
1 | package net.recommenders.rival.examples.mdp;
2 |
3 | import org.apache.commons.lang.NotImplementedException;
4 | import org.apache.mahout.cf.taste.common.TasteException;
5 | import org.apache.mahout.cf.taste.impl.recommender.GenericItemBasedRecommender;
6 | import org.apache.mahout.cf.taste.impl.similarity.AbstractItemSimilarity;
7 | import org.apache.mahout.cf.taste.impl.similarity.EuclideanDistanceSimilarity;
8 | import org.apache.mahout.cf.taste.impl.similarity.PearsonCorrelationSimilarity;
9 | import org.apache.mahout.cf.taste.impl.similarity.TanimotoCoefficientSimilarity;
10 | import org.apache.mahout.cf.taste.model.DataModel;
11 | import org.apache.mahout.cf.taste.recommender.Recommender;
12 |
13 | public class MahoutItemBasedCFRecSysEvaluator extends CrossValidationRecSysEvaluator {
14 |
15 | public enum Distance {PEARSON, EUCLIDEAN, TANIMOTO}
16 |
17 | private Distance distance;
18 |
19 | public MahoutItemBasedCFRecSysEvaluator(int numFolds, double relevanceThreshold, Distance distance) {
20 | super(numFolds, relevanceThreshold);
21 | this.distance = distance;
22 | }
23 |
24 | @Override
25 | protected Recommender buildRecommender(DataModel trainingModel) throws TasteException {
26 |
27 | AbstractItemSimilarity similarity;
28 |
29 | switch (this.distance) {
30 | case EUCLIDEAN:
31 | similarity = new EuclideanDistanceSimilarity(trainingModel);
32 | break;
33 | case TANIMOTO:
34 | similarity = new TanimotoCoefficientSimilarity(trainingModel);
35 | break;
36 | case PEARSON:
37 | similarity = new PearsonCorrelationSimilarity(trainingModel);
38 | break;
39 | default:
40 | throw new NotImplementedException("Unknown distance specified!");
41 | }
42 |
43 | return new GenericItemBasedRecommender(trainingModel, similarity);
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/rival-examples/src/main/java/net/recommenders/rival/examples/mdp/Main.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2016 recommenders.net.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package net.recommenders.rival.examples.mdp;
17 |
18 | /**
19 | *
20 | * @author Alejandro
21 | */
22 | public class Main {
23 |
24 | public static void main(String[] args) throws Exception {
25 | String datasetFile = "../../problem__marco_di_pietro/tripadvisor_ratings_u0_i0_.csv";
26 | String out = "../../problem__marco_di_pietro/";
27 |
28 | MahoutItemBasedCFRecSysEvaluator eval = new MahoutItemBasedCFRecSysEvaluator(/*5*/ 2, 4.0, MahoutItemBasedCFRecSysEvaluator.Distance.PEARSON);
29 | // eval.split(datasetFile, out, false, 0, ",");
30 | // eval.recommend(out, out);
31 | eval.buildEvaluationModels(out, out, out);
32 | eval.evaluate(out, out);
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/rival-examples/src/main/java/net/recommenders/rival/examples/movielens100k/package-info.java:
--------------------------------------------------------------------------------
1 | /**
2 | * RiVal movielens100k examples.
3 | */
4 | package net.recommenders.rival.examples.movielens100k;
5 |
--------------------------------------------------------------------------------
/rival-examples/src/main/java/net/recommenders/rival/examples/movietweetings/package-info.java:
--------------------------------------------------------------------------------
1 | /**
2 | * RiVal MovieTweetings examples.
3 | */
4 | package net.recommenders.rival.examples.movietweetings;
5 |
--------------------------------------------------------------------------------
/rival-examples/src/main/java/net/recommenders/rival/examples/package-info.java:
--------------------------------------------------------------------------------
1 | /**
2 | * RiVal examples.
3 | */
4 | package net.recommenders.rival.examples;
5 |
--------------------------------------------------------------------------------
/rival-package/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 4.0.0
4 |
5 | rival
6 | net.recommenders.rival
7 | 0.3-SNAPSHOT
8 | ..
9 |
10 | rival-package
11 | RiVal Package
12 |
13 | This module prepares the packaging of the binary RiVal distribution.
14 |
15 | pom
16 |
17 |
18 | ${project.build.directory}/jars
19 |
20 |
21 |
22 |
23 | net.recommenders.rival
24 | rival-core
25 | ${project.version}
26 |
27 |
28 | net.recommenders.rival
29 | rival-evaluate
30 | ${project.version}
31 |
32 |
33 | net.recommenders.rival
34 | rival-split
35 | ${project.version}
36 |
37 |
38 | net.recommenders.rival
39 | rival-recommend
40 | ${project.version}
41 |
42 |
43 |
44 |
45 |
46 |
47 | org.codehaus.mojo
48 | appassembler-maven-plugin
49 | 1.2
50 |
51 | ${project.build.directory}/dist/rival
52 | flat
53 | lib
54 |
55 |
59 |
60 |
61 |
62 |
63 | assemble
64 | package
65 |
66 | assemble
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 | release
77 |
78 | false
79 |
80 |
81 |
82 |
83 | org.apache.maven.plugins
84 | maven-antrun-plugin
85 |
86 |
87 | dist-package
88 | package
89 |
90 | run
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
--------------------------------------------------------------------------------
/rival-package/src/text/APL.txt:
--------------------------------------------------------------------------------
1 | Copyright 2015 recommenders.net
2 |
3 | Licensed under the Apache License, Version 2.0 (the "License");
4 | you may not use this file except in compliance with the License.
5 | You may obtain a copy of the License at
6 |
7 | http://www.apache.org/licenses/LICENSE-2.0
8 |
9 | Unless required by applicable law or agreed to in writing, software
10 | distributed under the License is distributed on an "AS IS" BASIS,
11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | See the License for the specific language governing permissions and
13 | limitations under the License.
--------------------------------------------------------------------------------
/rival-package/src/text/LICENSE.txt:
--------------------------------------------------------------------------------
1 | RiVal: an open source recommender systems evaluation toolkit.
2 | Copyright 2013-2015 recommenders.net
3 | Parts of the work on RiVal has received funding from the European
4 | Union Seventh Framework Programme (FP7/2007-2013) under grant
5 | agreement no.
6 |
7 | This program is distributed in the hope that it will be useful, but WITHOUT
8 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
9 | FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
10 | details.
11 |
12 |
13 | LensKit uses several libraries covered by the Apache Public License, version 2;
14 | this license is in the file APL.txt. A full list of licenses for third-paty
15 | software is in the file THIRD-PARTY.txt.
16 |
17 | SLF4J carries the following copyright:
18 |
19 | Copyright (c) 2004-2013 QOS.ch
20 | All rights reserved.
21 |
22 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software
23 | and associated documentation files (the "Software"), to deal in the Software without
24 | restriction, including without limitation the rights to use, copy, modify, merge, publish,
25 | distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom
26 | the Software is furnished to do so, subject to the following conditions:
27 |
28 | The above copyright notice and this permission notice shall be included in all copies or
29 | substantial portions of the Software.
30 |
31 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
32 | INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
33 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
34 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
35 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
36 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
--------------------------------------------------------------------------------
/rival-recommend/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 4.0.0
4 |
5 |
6 | net.recommenders.rival
7 | rival
8 | 0.3-SNAPSHOT
9 |
10 | rival-recommend
11 | jar
12 | RiVal Recommendation
13 |
14 |
15 |
16 | junit
17 | junit
18 | test
19 |
20 |
21 |
22 | net.recommenders.rival
23 | rival-core
24 | ${project.version}
25 |
26 |
27 |
28 | org.apache.mahout
29 | mahout-core
30 | ${mahout.version}
31 |
32 |
33 | commons-lang
34 | commons-lang
35 |
36 |
37 | asm
38 | asm
39 |
40 |
41 | org.apache.commons
42 | commons-lang3
43 |
44 |
45 | org.apache.commons
46 | commons-math3
47 |
48 |
49 |
50 |
51 |
52 | org.lenskit
53 | lenskit-core
54 | ${lenskit.version}
55 |
56 |
57 | org.apache.commons
58 | commons-lang3
59 |
60 |
61 |
62 |
63 |
64 | org.lenskit
65 | lenskit-knn
66 | ${lenskit.version}
67 |
68 |
69 |
70 | org.lenskit
71 | lenskit-svd
72 | ${lenskit.version}
73 |
74 |
75 |
76 | net.librec
77 | librec-core
78 | ${librec.version}
79 |
80 |
81 | commons-lang
82 | commons-lang
83 |
84 |
85 |
86 |
87 |
88 | org.ranksys.RankSys
89 | RankSys-core
90 | ${ranksys.version}
91 |
92 |
93 | org.ranksys.RankSys
94 | RankSys-fast
95 | ${ranksys.version}
96 |
97 |
98 | org.ranksys.RankSys
99 | RankSys-formats
100 | ${ranksys.version}
101 |
102 |
103 | org.ranksys.RankSys
104 | RankSys-mf
105 | ${ranksys.version}
106 |
107 |
108 | org.ranksys.RankSys
109 | RankSys-nn
110 | ${ranksys.version}
111 |
112 |
113 |
114 |
115 | org.slf4j
116 | slf4j-simple
117 | 1.6.6
118 |
119 |
120 | org.apache.commons
121 | commons-lang3
122 | 3.6
123 |
124 |
125 |
126 |
127 |
128 |
129 | org.apache.maven.plugins
130 | maven-compiler-plugin
131 |
132 |
133 | org.codehaus.mojo
134 | exec-maven-plugin
135 |
136 | java
137 | net.recommenders.rival.recommend.frameworks.MultipleRecommendationRunner
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
--------------------------------------------------------------------------------
/rival-recommend/src/main/java/net/recommenders/rival/recommend/frameworks/RecommenderIO.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2015 recommenders.net.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package net.recommenders.rival.recommend.frameworks;
17 |
18 | //import org.grouplens.lenskit.scored.ScoredId;
19 |
20 | import java.io.BufferedWriter;
21 | import java.io.File;
22 | import java.io.FileOutputStream;
23 | import java.io.IOException;
24 | import java.io.OutputStreamWriter;
25 | import java.util.List;
26 | import net.recommenders.rival.core.TemporalDataModelIF;
27 |
28 | /**
29 | * Recommender-related IO operations.
30 | *
31 | * @author Alan.
32 | */
33 | public final class RecommenderIO {
34 |
35 | /**
36 | * Utility classes should not have a public or default constructor.
37 | */
38 | private RecommenderIO() {
39 | }
40 |
41 | /**
42 | * Write recommendations to file.
43 | *
44 | * @param user the user
45 | * @param recommendations the recommendations
46 | * @param path directory where fileName will be written (if not null)
47 | * @param fileName name of the file, if null recommendations will not be
48 | * printed
49 | * @param append flag to decide if recommendations should be appended to
50 | * file
51 | * @param model if not null, recommendations will be saved here
52 | */
53 | public static void writeData(final long user, final List> recommendations, final String path, final String fileName, final boolean append, final TemporalDataModelIF model) {
54 | BufferedWriter out = null;
55 | try {
56 | File dir = null;
57 | if (path != null) {
58 | dir = new File(path);
59 | if (!dir.isDirectory()) {
60 | if (!dir.mkdir() && (fileName != null)) {
61 | System.out.println("Directory " + path + " could not be created");
62 | return;
63 | }
64 | }
65 | }
66 | if ((path != null) && (fileName != null)) {
67 | out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(path + "/" + fileName, append), "UTF-8"));
68 | }
69 | for (Preference recItem : recommendations) {
70 | if (out != null) {
71 | out.write(user + "\t" + recItem.getItem()+ "\t" + recItem.getScore() + "\n");
72 | }
73 | if (model != null) {
74 | model.addPreference(user, recItem.getItem(), recItem.getScore());
75 | }
76 | }
77 | if (out != null) {
78 | out.flush();
79 | out.close();
80 | }
81 | } catch (IOException e) {
82 | System.out.println(e.getMessage());
83 | // logger.error(e.getMessage());
84 | } finally {
85 | if (out != null) {
86 | try {
87 | out.close();
88 | } catch (IOException e) {
89 | e.printStackTrace();
90 | }
91 | }
92 | }
93 | }
94 |
95 | public static class Preference {
96 |
97 | private U user;
98 | private I item;
99 | private double score;
100 |
101 | public Preference(U user, I item, double score) {
102 | this.user = user;
103 | this.item = item;
104 | this.score = score;
105 | }
106 |
107 | public U getUser() {
108 | return user;
109 | }
110 |
111 | public I getItem() {
112 | return item;
113 | }
114 |
115 | public double getScore() {
116 | return score;
117 | }
118 |
119 | }
120 | }
121 |
--------------------------------------------------------------------------------
/rival-recommend/src/main/java/net/recommenders/rival/recommend/frameworks/exceptions/RecommenderException.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2015 recommenders.net.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package net.recommenders.rival.recommend.frameworks.exceptions;
17 |
18 | /**
19 | * Exception to be used in the recommender module.
20 | *
21 | * @author Alan
22 | */
23 | @SuppressWarnings("serial")
24 | public class RecommenderException extends Exception {
25 |
26 | /**
27 | * Constructs an exception with the specified message.
28 | *
29 | * @param msg the message to be shown later.
30 | */
31 | public RecommenderException(final String msg) {
32 | super(msg);
33 | }
34 |
35 | /**
36 | * Constructs a new exception with the specified message and cause.
37 | *
38 | * @param msg the message to be shown later.
39 | * @param t the cause of the exception.
40 | */
41 | public RecommenderException(final String msg, final Throwable t) {
42 | super(msg, t);
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/rival-recommend/src/main/java/net/recommenders/rival/recommend/frameworks/exceptions/package-info.java:
--------------------------------------------------------------------------------
1 | /**
2 | * RiVal Exceptions used in the recommender module.
3 | */
4 | package net.recommenders.rival.recommend.frameworks.exceptions;
5 |
--------------------------------------------------------------------------------
/rival-recommend/src/main/java/net/recommenders/rival/recommend/frameworks/lenskit/EventDAOWrapper.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2015 recommenders.net.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package net.recommenders.rival.recommend.frameworks.lenskit;
17 |
18 | import it.unimi.dsi.fastutil.longs.LongSet;
19 | import java.util.ArrayList;
20 | import java.util.List;
21 | import java.util.Set;
22 | import net.recommenders.rival.core.TemporalDataModelIF;
23 | import org.lenskit.data.dao.DataAccessObject;
24 | import org.lenskit.data.dao.EntityCollectionDAO;
25 | import org.lenskit.data.dao.EntityQuery;
26 | import org.lenskit.data.dao.Query;
27 | import org.lenskit.data.entities.Entity;
28 | import org.lenskit.data.entities.EntityType;
29 | import org.lenskit.data.entities.TypedName;
30 | import org.lenskit.data.ratings.Rating;
31 | import org.lenskit.data.ratings.RatingBuilder;
32 | import org.lenskit.util.IdBox;
33 | import org.lenskit.util.io.ObjectStream;
34 |
35 | /**
36 | * Lenskit's EventDAO wrapper for {@link net.recommenders.rival.core.DataModel}.
37 | *
38 | * @author Alejandro
39 | */
40 | public class EventDAOWrapper implements DataAccessObject {
41 |
42 | /**
43 | * Serial version UID.
44 | */
45 | private static final long serialVersionUID = 170150729L;
46 | /**
47 | * Lenskit's DataAccessObject that will be used as wrapper.
48 | */
49 | private DataAccessObject wrapper;
50 |
51 | /**
52 | * Constructs the wrapper using the provided model.
53 | *
54 | * @param model the model to be used to create the wrapped model
55 | */
56 | public EventDAOWrapper(final TemporalDataModelIF model) {
57 | List events = new ArrayList<>();
58 | RatingBuilder rb = new RatingBuilder();
59 | for (Long u : model.getUsers()) {
60 | rb.setUserId(u);
61 | for (Long i : model.getUserItems(u)) {
62 | rb.setItemId(i);
63 | rb.setRating(model.getUserItemPreference(u, i));
64 | Iterable timestamps = model.getUserItemTimestamps(u, i);
65 | long t = -1;
66 | if (timestamps != null) {
67 | for (Long tt : timestamps) {
68 | t = tt;
69 | break;
70 | }
71 | }
72 | rb.setTimestamp(t);
73 | events.add(rb.build());
74 | }
75 | }
76 | wrapper = EntityCollectionDAO.create(events);
77 | }
78 |
79 | /**
80 | * {@inheritDoc}
81 | */
82 | @Override
83 | public Set getEntityTypes() {
84 | return wrapper.getEntityTypes();
85 | }
86 |
87 | /**
88 | * {@inheritDoc}
89 | */
90 | @Override
91 | public LongSet getEntityIds(EntityType et) {
92 | return wrapper.getEntityIds(et);
93 | }
94 |
95 | /**
96 | * {@inheritDoc}
97 | */
98 | @Override
99 | public Entity lookupEntity(EntityType et, long l) {
100 | return wrapper.lookupEntity(et, l);
101 | }
102 |
103 | /**
104 | * {@inheritDoc}
105 | */
106 | @Override
107 | public E lookupEntity(EntityType et, long l, Class type) {
108 | return wrapper.lookupEntity(et, l, type);
109 | }
110 |
111 | /**
112 | * {@inheritDoc}
113 | */
114 | @Override
115 | public ObjectStream streamEntities(EntityType et) {
116 | return wrapper.streamEntities(et);
117 | }
118 |
119 | /**
120 | * {@inheritDoc}
121 | */
122 | @Override
123 | public ObjectStream streamEntities(EntityQuery eq) {
124 | return wrapper.streamEntities(eq);
125 | }
126 |
127 | /**
128 | * {@inheritDoc}
129 | */
130 | @Override
131 | public ObjectStream>> streamEntityGroups(EntityQuery eq, TypedName tn) {
132 | return wrapper.streamEntityGroups(eq, tn);
133 | }
134 |
135 | /**
136 | * {@inheritDoc}
137 | */
138 | @Override
139 | public Query query(EntityType et) {
140 | return wrapper.query(et);
141 | }
142 |
143 | /**
144 | * {@inheritDoc}
145 | */
146 | @Override
147 | public Query query(Class type) {
148 | return wrapper.query(type);
149 | }
150 | }
151 |
--------------------------------------------------------------------------------
/rival-recommend/src/main/java/net/recommenders/rival/recommend/frameworks/lenskit/package-info.java:
--------------------------------------------------------------------------------
1 | /**
2 | * RiVal Lenskit recommender interface.
3 | */
4 | package net.recommenders.rival.recommend.frameworks.lenskit;
5 |
--------------------------------------------------------------------------------
/rival-recommend/src/main/java/net/recommenders/rival/recommend/frameworks/librec/DataDAOWrapper.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2016 recommenders.net.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package net.recommenders.rival.recommend.frameworks.librec;
17 |
18 | import com.google.common.collect.BiMap;
19 | import java.io.File;
20 | import java.io.PrintStream;
21 | import net.librec.common.LibrecException;
22 | import net.librec.conf.Configuration;
23 | import net.librec.conf.Configured;
24 | import net.librec.data.DataAppender;
25 | import net.librec.data.DataContext;
26 | import net.librec.data.DataModel;
27 | import net.librec.data.DataSplitter;
28 | import net.librec.data.model.TextDataModel;
29 | import net.librec.math.structure.DataSet;
30 | import net.recommenders.rival.core.TemporalDataModelIF;
31 |
32 | /**
33 | *
34 | * @author Alejandro
35 | */
36 | public class DataDAOWrapper implements DataModel {
37 |
38 | /**
39 | * Serial version UID.
40 | */
41 | private static final long serialVersionUID = 170160729L;
42 | /**
43 | * Librec's DataModel that will be used as wrapper.
44 | */
45 | private DataModel wrapper;
46 |
47 | /**
48 | * Constructs the wrapper using the provided model.
49 | *
50 | * @param model the model to be used to create the wrapped model
51 | */
52 | public DataDAOWrapper(final TemporalDataModelIF model) {
53 | super();
54 | try {
55 | // generate file based on the model
56 | File path = File.createTempFile("librec", "datadao");
57 | PrintStream out = new PrintStream(path);
58 | for (Long u : model.getUsers()) {
59 | for (Long i : model.getUserItems(u)) {
60 | Double d = model.getUserItemPreference(u, i);
61 | Iterable time = model.getUserItemTimestamps(u, i);
62 | if (time == null) {
63 | out.println(u + "\t" + i + "\t" + d);
64 | } else {
65 | for (Long t : time) {
66 | out.println(u + "\t" + i + "\t" + d + "\t" + t);
67 | break;
68 | }
69 | }
70 | }
71 | }
72 | out.close();
73 | // create the wrapper based on this file
74 | Configuration confTraining = new Configuration();
75 | confTraining.set(Configured.CONF_DATA_INPUT_PATH, path.getAbsolutePath());
76 | confTraining.set(Configured.CONF_DATA_COLUMN_FORMAT, "UIR");
77 | confTraining.set("data.model.splitter", "ratio");
78 | confTraining.set("data.splitter.trainset.ratio", "0.999");
79 | confTraining.set("data.splitter.ratio", "rating");
80 | wrapper = new TextDataModel(confTraining);
81 | wrapper.buildDataModel();
82 | } catch (Exception e) {
83 | e.printStackTrace();
84 | }
85 | }
86 |
87 | @Override
88 | public void buildDataModel() throws LibrecException {
89 | wrapper.buildDataModel();
90 | }
91 |
92 | @Override
93 | public void loadDataModel() throws LibrecException {
94 | wrapper.loadDataModel();
95 | }
96 |
97 | @Override
98 | public void saveDataModel() throws LibrecException {
99 | wrapper.saveDataModel();
100 | }
101 |
102 | @Override
103 | public DataSplitter getDataSplitter() {
104 | return wrapper.getDataSplitter();
105 | }
106 |
107 | @Override
108 | public DataSet getTrainDataSet() {
109 | return wrapper.getTrainDataSet();
110 | }
111 |
112 | @Override
113 | public DataSet getTestDataSet() {
114 | return wrapper.getTestDataSet();
115 | }
116 |
117 | @Override
118 | public DataSet getValidDataSet() {
119 | return wrapper.getValidDataSet();
120 | }
121 |
122 | @Override
123 | public DataSet getDatetimeDataSet() {
124 | return wrapper.getDatetimeDataSet();
125 | }
126 |
127 | @Override
128 | public BiMap getUserMappingData() {
129 | return wrapper.getUserMappingData();
130 | }
131 |
132 | @Override
133 | public BiMap getItemMappingData() {
134 | return wrapper.getItemMappingData();
135 | }
136 |
137 | @Override
138 | public DataAppender getDataAppender() {
139 | return wrapper.getDataAppender();
140 | }
141 |
142 | @Override
143 | public DataContext getContext() {
144 | return wrapper.getContext();
145 | }
146 |
147 | }
148 |
--------------------------------------------------------------------------------
/rival-recommend/src/main/java/net/recommenders/rival/recommend/frameworks/mahout/PopularityBasedRecommender.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2015 recommenders.net.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package net.recommenders.rival.recommend.frameworks.mahout;
17 |
18 | import java.util.Collection;
19 | import java.util.List;
20 | import org.apache.mahout.cf.taste.common.Refreshable;
21 | import org.apache.mahout.cf.taste.common.TasteException;
22 | import org.apache.mahout.cf.taste.impl.recommender.AbstractRecommender;
23 | import org.apache.mahout.cf.taste.model.DataModel;
24 | import org.apache.mahout.cf.taste.recommender.CandidateItemsStrategy;
25 | import org.apache.mahout.cf.taste.recommender.IDRescorer;
26 | import org.apache.mahout.cf.taste.recommender.RecommendedItem;
27 | import org.apache.mahout.cf.taste.recommender.Recommender;
28 |
29 | /**
30 | * Basic popularity-based recommender.
31 | *
32 | * @author Alejandro
33 | */
34 | public class PopularityBasedRecommender extends AbstractRecommender implements Recommender {
35 |
36 | /**
37 | * Constructor when a canidate item strategy is to be used.
38 | *
39 | * @param dataModel the data model
40 | * @param candidateItemsStrategy the strategy
41 | */
42 | public PopularityBasedRecommender(final DataModel dataModel, final CandidateItemsStrategy candidateItemsStrategy) {
43 | super(dataModel, candidateItemsStrategy);
44 | }
45 |
46 | /**
47 | * Default constructor.
48 | *
49 | * @param dataModel the data model.
50 | */
51 | public PopularityBasedRecommender(final DataModel dataModel) {
52 | super(dataModel);
53 | }
54 |
55 | /**
56 | * Estimate the preference of @u of @i.
57 | *
58 | * @param u the user
59 | * @param i the item
60 | * @return the preference
61 | * @throws TasteException when the recommender cannot estimate the
62 | * preference.
63 | */
64 | @Override
65 | public float estimatePreference(final long u, final long i) throws TasteException {
66 | return 1.0f * getDataModel().getPreferencesForItem(i).length();
67 | }
68 |
69 | /**
70 | * Recommend items to a user.
71 | *
72 | * @param userID the user
73 | * @param howMany how many items to recommend
74 | * @param rescorer what rescorer to use
75 | * @return the list of recommendations
76 | * @throws TasteException if something in the recommender breaks.
77 | */
78 | public List recommend(final long userID, final int howMany, final IDRescorer rescorer) throws TasteException {
79 | throw new UnsupportedOperationException("Not supported yet.");
80 | }
81 |
82 | /**
83 | * Refresh the recommender.
84 | *
85 | * @param clctn the data.
86 | */
87 | @Override
88 | public void refresh(final Collection clctn) {
89 | }
90 | }
91 |
--------------------------------------------------------------------------------
/rival-recommend/src/main/java/net/recommenders/rival/recommend/frameworks/mahout/package-info.java:
--------------------------------------------------------------------------------
1 | /**
2 | * RiVal Mahout recommender interface.
3 | */
4 | package net.recommenders.rival.recommend.frameworks.mahout;
5 |
--------------------------------------------------------------------------------
/rival-recommend/src/main/java/net/recommenders/rival/recommend/frameworks/package-info.java:
--------------------------------------------------------------------------------
1 | /**
2 | * RiVal interfaces to recommender frameworks.
3 | */
4 | package net.recommenders.rival.recommend.frameworks;
5 |
--------------------------------------------------------------------------------
/rival-recommend/src/main/java/net/recommenders/rival/recommend/frameworks/ranksys/ItemIndexWrapper.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2017 recommenders.net.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package net.recommenders.rival.recommend.frameworks.ranksys;
17 |
18 | import es.uam.eps.ir.ranksys.fast.index.FastItemIndex;
19 | import es.uam.eps.ir.ranksys.fast.index.SimpleFastItemIndex;
20 | import java.util.HashSet;
21 | import java.util.Set;
22 | import java.util.stream.Stream;
23 | import net.recommenders.rival.core.TemporalDataModelIF;
24 |
25 | /**
26 | *
27 | * @author Alejandro
28 | */
29 | public class ItemIndexWrapper implements FastItemIndex {
30 |
31 | private final FastItemIndex wrapper;
32 |
33 | public ItemIndexWrapper(TemporalDataModelIF training, TemporalDataModelIF test) {
34 | Set