├── .gitignore ├── .mvn └── wrapper │ ├── maven-wrapper.jar │ └── maven-wrapper.properties ├── README.md ├── data ├── README.md ├── news.sql ├── user.sql └── useroperation.sql ├── mvnw ├── mvnw.cmd ├── pom.xml └── src ├── main ├── java │ └── com │ │ └── kadoufall │ │ └── recommender │ │ ├── RecommenderApplication.java │ │ ├── dao │ │ ├── NewsRepository.java │ │ ├── UserOperationRepository.java │ │ ├── UserRepository.java │ │ ├── UtilRepositoryCustom.java │ │ └── UtilRepositoryImpl.java │ │ ├── model │ │ ├── News.java │ │ ├── User.java │ │ └── UserOperation.java │ │ ├── service │ │ ├── contentBased │ │ │ ├── ContentBasedRecommenderService.java │ │ │ ├── ContentBasedRecommenderServiceImpl.java │ │ │ ├── NewsItemSimilarity.java │ │ │ └── TrainVsmModel.java │ │ ├── hot │ │ │ ├── HotRecommenderService.java │ │ │ └── HotRecommenderServiceImpl.java │ │ ├── userCF │ │ │ ├── UserCFRecommenderService.java │ │ │ └── UserCFRecommenderServiceImpl.java │ │ └── util │ │ │ ├── UtilService.java │ │ │ └── UtilServiceImpl.java │ │ └── web │ │ └── RecommendController.java └── resources │ ├── README.md │ ├── application.properties │ ├── caixin.base │ ├── caixinWords.txt │ ├── log4j.properties │ └── stopword.txt └── test └── java └── com └── kadoufall └── recommender ├── RecommenderApplicationTests.java ├── dao └── DomainTest.java ├── recommender ├── EvaluateTest.java └── MahoutTest.java └── service ├── ContentBasedRecommenderServiceTest.java └── HotRecommenderServiceTest.java /.gitignore: -------------------------------------------------------------------------------- 1 | /target/ 2 | !.mvn/wrapper/maven-wrapper.jar 3 | 4 | ### STS ### 5 | .apt_generated 6 | .classpath 7 | .factorypath 8 | .project 9 | .settings 10 | .springBeans 11 | .sts4-cache 12 | 13 | ### IntelliJ IDEA ### 14 | .idea 15 | *.iws 16 | *.iml 17 | *.ipr 18 | 19 | ### NetBeans ### 20 | /nbproject/private/ 21 | /build/ 22 | /nbbuild/ 23 | /dist/ 24 | /nbdist/ 25 | /.nb-gradle/ 26 | 27 | /logs/* -------------------------------------------------------------------------------- /.mvn/wrapper/maven-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kadoufall/news-recommender/ccecbe6b918ebe537442976dbb6fbc17aa92f958/.mvn/wrapper/maven-wrapper.jar -------------------------------------------------------------------------------- /.mvn/wrapper/maven-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionUrl=https://repo1.maven.org/maven2/org/apache/maven/apache-maven/3.5.3/apache-maven-3.5.3-bin.zip 2 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 基于Mahout的新闻推荐系统 2 | 3 | ## 相关技术 4 | 5 | - 推荐算法 6 | - 基于用户的协同过滤 7 | - 基于内容的推荐 8 | - 基于热点的推荐 9 | 10 | - [Mahout](http://mahout.apache.org/):整体框架,实现了协同过滤 11 | - [Deeplearning4j](https://deeplearning4j.org/),构建VSM 12 | - [Jieba](https://github.com/fxsjy/jieba):分词,关键词提取 13 | - [HanLP](https://github.com/hankcs/HanLP):分词,关键词提取 14 | - [Spring Boot](https://spring.io/):提供API、ORM 15 | 16 | 17 | ## 关键实现 18 | 19 | ### 基于用户的协同过滤 20 | - 直接调用Mahout相关接口即可 21 | - 选择不同的用户相似度度量方法,这里选择了基于谷本系数、基于对数似然和基于曼哈顿距离 22 | 23 | ### 基于内容的推荐 24 | - 对新闻文本进行分词 25 | - 调用Deeplearning4j中构建paragraphvector的方法,通过doc2vec构建VSM 26 | - 用Gensim会更方便点 27 | 28 | 29 | ### 基于热点的推荐 30 | - 统计最高浏览量 31 | - 过滤一定时间前的新闻保证热点的准确 32 | 33 | ## 评测指标 34 | - [测试数据集](https://pan.baidu.com/s/1Y84iLIY8RbO_6oFTEm1oGA#list/path=%2F) 35 | - F1-Measure(precision + recall) 36 | 37 | |算法|最近邻数量K|推荐数N|F1-Measure| 38 | |:---:|:---:|:---:|:---:| 39 | |UserCF--Tanimoto|20|11|0.481591183699049| 40 | |UserCF--LogLike|10|11|0.486337485027766| 41 | |UserCF--CityBlock|30|8|0.424612102745937| 42 | |ContentBased|-|5|0.0491655390166893| 43 | |HotSpots|-|14|0.118524972063865| 44 | 45 | 46 | -------------------------------------------------------------------------------- /data/README.md: -------------------------------------------------------------------------------- 1 | ## 预处理后的 MySQL 结构和数据 2 | 3 | - news 4 | - user 5 | - userOperation -------------------------------------------------------------------------------- /mvnw: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # ---------------------------------------------------------------------------- 3 | # Licensed to the Apache Software Foundation (ASF) under one 4 | # or more contributor license agreements. See the NOTICE file 5 | # distributed with this work for additional information 6 | # regarding copyright ownership. The ASF licenses this file 7 | # to you under the Apache License, Version 2.0 (the 8 | # "License"); you may not use this file except in compliance 9 | # with the License. You may obtain a copy of the License at 10 | # 11 | # http://www.apache.org/licenses/LICENSE-2.0 12 | # 13 | # Unless required by applicable law or agreed to in writing, 14 | # software distributed under the License is distributed on an 15 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 | # KIND, either express or implied. See the License for the 17 | # specific language governing permissions and limitations 18 | # under the License. 19 | # ---------------------------------------------------------------------------- 20 | 21 | # ---------------------------------------------------------------------------- 22 | # Maven2 Start Up Batch script 23 | # 24 | # Required ENV vars: 25 | # ------------------ 26 | # JAVA_HOME - location of a JDK home dir 27 | # 28 | # Optional ENV vars 29 | # ----------------- 30 | # M2_HOME - location of maven2's installed home dir 31 | # MAVEN_OPTS - parameters passed to the Java VM when running Maven 32 | # e.g. to debug Maven itself, use 33 | # set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 34 | # MAVEN_SKIP_RC - flag to disable loading of mavenrc files 35 | # ---------------------------------------------------------------------------- 36 | 37 | if [ -z "$MAVEN_SKIP_RC" ] ; then 38 | 39 | if [ -f /etc/mavenrc ] ; then 40 | . /etc/mavenrc 41 | fi 42 | 43 | if [ -f "$HOME/.mavenrc" ] ; then 44 | . "$HOME/.mavenrc" 45 | fi 46 | 47 | fi 48 | 49 | # OS specific support. $var _must_ be set to either true or false. 50 | cygwin=false; 51 | darwin=false; 52 | mingw=false 53 | case "`uname`" in 54 | CYGWIN*) cygwin=true ;; 55 | MINGW*) mingw=true;; 56 | Darwin*) darwin=true 57 | # Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home 58 | # See https://developer.apple.com/library/mac/qa/qa1170/_index.html 59 | if [ -z "$JAVA_HOME" ]; then 60 | if [ -x "/usr/libexec/java_home" ]; then 61 | export JAVA_HOME="`/usr/libexec/java_home`" 62 | else 63 | export JAVA_HOME="/Library/Java/Home" 64 | fi 65 | fi 66 | ;; 67 | esac 68 | 69 | if [ -z "$JAVA_HOME" ] ; then 70 | if [ -r /etc/gentoo-release ] ; then 71 | JAVA_HOME=`java-config --jre-home` 72 | fi 73 | fi 74 | 75 | if [ -z "$M2_HOME" ] ; then 76 | ## resolve links - $0 may be a link to maven's home 77 | PRG="$0" 78 | 79 | # need this for relative symlinks 80 | while [ -h "$PRG" ] ; do 81 | ls=`ls -ld "$PRG"` 82 | link=`expr "$ls" : '.*-> \(.*\)$'` 83 | if expr "$link" : '/.*' > /dev/null; then 84 | PRG="$link" 85 | else 86 | PRG="`dirname "$PRG"`/$link" 87 | fi 88 | done 89 | 90 | saveddir=`pwd` 91 | 92 | M2_HOME=`dirname "$PRG"`/.. 93 | 94 | # make it fully qualified 95 | M2_HOME=`cd "$M2_HOME" && pwd` 96 | 97 | cd "$saveddir" 98 | # echo Using m2 at $M2_HOME 99 | fi 100 | 101 | # For Cygwin, ensure paths are in UNIX format before anything is touched 102 | if $cygwin ; then 103 | [ -n "$M2_HOME" ] && 104 | M2_HOME=`cygpath --unix "$M2_HOME"` 105 | [ -n "$JAVA_HOME" ] && 106 | JAVA_HOME=`cygpath --unix "$JAVA_HOME"` 107 | [ -n "$CLASSPATH" ] && 108 | CLASSPATH=`cygpath --path --unix "$CLASSPATH"` 109 | fi 110 | 111 | # For Migwn, ensure paths are in UNIX format before anything is touched 112 | if $mingw ; then 113 | [ -n "$M2_HOME" ] && 114 | M2_HOME="`(cd "$M2_HOME"; pwd)`" 115 | [ -n "$JAVA_HOME" ] && 116 | JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`" 117 | # TODO classpath? 118 | fi 119 | 120 | if [ -z "$JAVA_HOME" ]; then 121 | javaExecutable="`which javac`" 122 | if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then 123 | # readlink(1) is not available as standard on Solaris 10. 124 | readLink=`which readlink` 125 | if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then 126 | if $darwin ; then 127 | javaHome="`dirname \"$javaExecutable\"`" 128 | javaExecutable="`cd \"$javaHome\" && pwd -P`/javac" 129 | else 130 | javaExecutable="`readlink -f \"$javaExecutable\"`" 131 | fi 132 | javaHome="`dirname \"$javaExecutable\"`" 133 | javaHome=`expr "$javaHome" : '\(.*\)/bin'` 134 | JAVA_HOME="$javaHome" 135 | export JAVA_HOME 136 | fi 137 | fi 138 | fi 139 | 140 | if [ -z "$JAVACMD" ] ; then 141 | if [ -n "$JAVA_HOME" ] ; then 142 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 143 | # IBM's JDK on AIX uses strange locations for the executables 144 | JAVACMD="$JAVA_HOME/jre/sh/java" 145 | else 146 | JAVACMD="$JAVA_HOME/bin/java" 147 | fi 148 | else 149 | JAVACMD="`which java`" 150 | fi 151 | fi 152 | 153 | if [ ! -x "$JAVACMD" ] ; then 154 | echo "Error: JAVA_HOME is not defined correctly." >&2 155 | echo " We cannot execute $JAVACMD" >&2 156 | exit 1 157 | fi 158 | 159 | if [ -z "$JAVA_HOME" ] ; then 160 | echo "Warning: JAVA_HOME environment variable is not set." 161 | fi 162 | 163 | CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher 164 | 165 | # traverses directory structure from process work directory to filesystem root 166 | # first directory with .mvn subdirectory is considered project base directory 167 | find_maven_basedir() { 168 | 169 | if [ -z "$1" ] 170 | then 171 | echo "Path not specified to find_maven_basedir" 172 | return 1 173 | fi 174 | 175 | basedir="$1" 176 | wdir="$1" 177 | while [ "$wdir" != '/' ] ; do 178 | if [ -d "$wdir"/.mvn ] ; then 179 | basedir=$wdir 180 | break 181 | fi 182 | # workaround for JBEAP-8937 (on Solaris 10/Sparc) 183 | if [ -d "${wdir}" ]; then 184 | wdir=`cd "$wdir/.."; pwd` 185 | fi 186 | # end of workaround 187 | done 188 | echo "${basedir}" 189 | } 190 | 191 | # concatenates all lines of a file 192 | concat_lines() { 193 | if [ -f "$1" ]; then 194 | echo "$(tr -s '\n' ' ' < "$1")" 195 | fi 196 | } 197 | 198 | BASE_DIR=`find_maven_basedir "$(pwd)"` 199 | if [ -z "$BASE_DIR" ]; then 200 | exit 1; 201 | fi 202 | 203 | export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"} 204 | echo $MAVEN_PROJECTBASEDIR 205 | MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS" 206 | 207 | # For Cygwin, switch paths to Windows format before running java 208 | if $cygwin; then 209 | [ -n "$M2_HOME" ] && 210 | M2_HOME=`cygpath --path --windows "$M2_HOME"` 211 | [ -n "$JAVA_HOME" ] && 212 | JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"` 213 | [ -n "$CLASSPATH" ] && 214 | CLASSPATH=`cygpath --path --windows "$CLASSPATH"` 215 | [ -n "$MAVEN_PROJECTBASEDIR" ] && 216 | MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"` 217 | fi 218 | 219 | WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain 220 | 221 | exec "$JAVACMD" \ 222 | $MAVEN_OPTS \ 223 | -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \ 224 | "-Dmaven.home=${M2_HOME}" "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \ 225 | ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@" 226 | -------------------------------------------------------------------------------- /mvnw.cmd: -------------------------------------------------------------------------------- 1 | @REM ---------------------------------------------------------------------------- 2 | @REM Licensed to the Apache Software Foundation (ASF) under one 3 | @REM or more contributor license agreements. See the NOTICE file 4 | @REM distributed with this work for additional information 5 | @REM regarding copyright ownership. The ASF licenses this file 6 | @REM to you under the Apache License, Version 2.0 (the 7 | @REM "License"); you may not use this file except in compliance 8 | @REM with the License. You may obtain a copy of the License at 9 | @REM 10 | @REM http://www.apache.org/licenses/LICENSE-2.0 11 | @REM 12 | @REM Unless required by applicable law or agreed to in writing, 13 | @REM software distributed under the License is distributed on an 14 | @REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | @REM KIND, either express or implied. See the License for the 16 | @REM specific language governing permissions and limitations 17 | @REM under the License. 18 | @REM ---------------------------------------------------------------------------- 19 | 20 | @REM ---------------------------------------------------------------------------- 21 | @REM Maven2 Start Up Batch script 22 | @REM 23 | @REM Required ENV vars: 24 | @REM JAVA_HOME - location of a JDK home dir 25 | @REM 26 | @REM Optional ENV vars 27 | @REM M2_HOME - location of maven2's installed home dir 28 | @REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands 29 | @REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a key stroke before ending 30 | @REM MAVEN_OPTS - parameters passed to the Java VM when running Maven 31 | @REM e.g. to debug Maven itself, use 32 | @REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 33 | @REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files 34 | @REM ---------------------------------------------------------------------------- 35 | 36 | @REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on' 37 | @echo off 38 | @REM enable echoing my setting MAVEN_BATCH_ECHO to 'on' 39 | @if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO% 40 | 41 | @REM set %HOME% to equivalent of $HOME 42 | if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%") 43 | 44 | @REM Execute a user defined script before this one 45 | if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre 46 | @REM check for pre script, once with legacy .bat ending and once with .cmd ending 47 | if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat" 48 | if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd" 49 | :skipRcPre 50 | 51 | @setlocal 52 | 53 | set ERROR_CODE=0 54 | 55 | @REM To isolate internal variables from possible post scripts, we use another setlocal 56 | @setlocal 57 | 58 | @REM ==== START VALIDATION ==== 59 | if not "%JAVA_HOME%" == "" goto OkJHome 60 | 61 | echo. 62 | echo Error: JAVA_HOME not found in your environment. >&2 63 | echo Please set the JAVA_HOME variable in your environment to match the >&2 64 | echo location of your Java installation. >&2 65 | echo. 66 | goto error 67 | 68 | :OkJHome 69 | if exist "%JAVA_HOME%\bin\java.exe" goto init 70 | 71 | echo. 72 | echo Error: JAVA_HOME is set to an invalid directory. >&2 73 | echo JAVA_HOME = "%JAVA_HOME%" >&2 74 | echo Please set the JAVA_HOME variable in your environment to match the >&2 75 | echo location of your Java installation. >&2 76 | echo. 77 | goto error 78 | 79 | @REM ==== END VALIDATION ==== 80 | 81 | :init 82 | 83 | @REM Find the project base dir, i.e. the directory that contains the folder ".mvn". 84 | @REM Fallback to current working directory if not found. 85 | 86 | set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR% 87 | IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir 88 | 89 | set EXEC_DIR=%CD% 90 | set WDIR=%EXEC_DIR% 91 | :findBaseDir 92 | IF EXIST "%WDIR%"\.mvn goto baseDirFound 93 | cd .. 94 | IF "%WDIR%"=="%CD%" goto baseDirNotFound 95 | set WDIR=%CD% 96 | goto findBaseDir 97 | 98 | :baseDirFound 99 | set MAVEN_PROJECTBASEDIR=%WDIR% 100 | cd "%EXEC_DIR%" 101 | goto endDetectBaseDir 102 | 103 | :baseDirNotFound 104 | set MAVEN_PROJECTBASEDIR=%EXEC_DIR% 105 | cd "%EXEC_DIR%" 106 | 107 | :endDetectBaseDir 108 | 109 | IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig 110 | 111 | @setlocal EnableExtensions EnableDelayedExpansion 112 | for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a 113 | @endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS% 114 | 115 | :endReadAdditionalConfig 116 | 117 | SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe" 118 | 119 | set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar" 120 | set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain 121 | 122 | %MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %* 123 | if ERRORLEVEL 1 goto error 124 | goto end 125 | 126 | :error 127 | set ERROR_CODE=1 128 | 129 | :end 130 | @endlocal & set ERROR_CODE=%ERROR_CODE% 131 | 132 | if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost 133 | @REM check for post script, once with legacy .bat ending and once with .cmd ending 134 | if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat" 135 | if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd" 136 | :skipRcPost 137 | 138 | @REM pause the script if MAVEN_BATCH_PAUSE is set to 'on' 139 | if "%MAVEN_BATCH_PAUSE%" == "on" pause 140 | 141 | if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE% 142 | 143 | exit /B %ERROR_CODE% 144 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 4.0.0 5 | 6 | com.kadoufall 7 | recommender 8 | 0.0.1-SNAPSHOT 9 | jar 10 | 11 | recommender 12 | Recommender for Todayim 13 | 14 | 15 | org.springframework.boot 16 | spring-boot-starter-parent 17 | 2.0.1.RELEASE 18 | 19 | 20 | 21 | 22 | UTF-8 23 | UTF-8 24 | 1.8 25 | 26 | 27 | 28 | 29 | org.springframework.boot 30 | spring-boot-starter 31 | 32 | 33 | org.springframework.boot 34 | spring-boot-starter-logging 35 | 36 | 37 | 38 | 39 | 40 | org.springframework.boot 41 | spring-boot-starter-log4j 42 | 43 | 44 | 45 | 46 | org.springframework.boot 47 | spring-boot-starter-data-jpa 48 | 49 | 50 | org.springframework.boot 51 | spring-boot-starter-integration 52 | 53 | 54 | org.springframework.boot 55 | spring-boot-starter-jdbc 56 | 57 | 58 | org.springframework.boot 59 | spring-boot-starter-web 60 | 61 | 62 | 63 | org.springframework.boot 64 | spring-boot-devtools 65 | runtime 66 | 67 | 68 | 69 | mysql 70 | mysql-connector-java 71 | runtime 72 | 73 | 74 | 75 | org.springframework.boot 76 | spring-boot-starter-test 77 | test 78 | 79 | 80 | 81 | org.springframework.boot 82 | spring-boot-configuration-processor 83 | true 84 | 85 | 86 | 87 | org.projectlombok 88 | lombok 89 | 90 | 91 | 92 | 93 | org.apache.mahout 94 | mahout-core 95 | 0.9 96 | 97 | 98 | 99 | 100 | org.apache.mahout 101 | mahout-math 102 | 0.13.0 103 | 104 | 105 | 106 | 107 | org.apache.mahout 108 | mahout-integration 109 | 0.13.0 110 | 111 | 112 | 113 | com.alibaba 114 | fastjson 115 | 1.2.46 116 | 117 | 118 | 119 | org.ansj 120 | ansj_seg 121 | 5.1.1 122 | 123 | 124 | 125 | 126 | org.deeplearning4j 127 | deeplearning4j-core 128 | 1.0.0-alpha 129 | 130 | 131 | 132 | 133 | org.deeplearning4j 134 | deeplearning4j-nlp 135 | 1.0.0-alpha 136 | 137 | 138 | 139 | 140 | org.deeplearning4j 141 | deeplearning4j-nn 142 | 1.0.0-alpha 143 | 144 | 145 | 146 | 147 | org.deeplearning4j 148 | arbiter-core 149 | 1.0.0-alpha 150 | 151 | 152 | 153 | 154 | org.deeplearning4j 155 | rl4j-api 156 | 1.0.0-alpha 157 | 158 | 159 | 160 | 161 | org.deeplearning4j 162 | deeplearning4j-modelimport 163 | 1.0.0-alpha 164 | 165 | 166 | 167 | 168 | org.deeplearning4j 169 | deeplearning4j-datavec-iterators 170 | 1.0.0-alpha 171 | 172 | 173 | 174 | 175 | org.nd4j 176 | nd4j-api 177 | 1.0.0-alpha 178 | 179 | 180 | 181 | 182 | org.nd4j 183 | nd4j-x86 184 | 0.4-rc3.8 185 | test 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | org.bytedeco 199 | javacpp 200 | 1.4.1 201 | 202 | 203 | 204 | 205 | org.apache.poi 206 | poi 207 | 3.17 208 | 209 | 210 | 211 | 212 | org.apache.poi 213 | poi-ooxml 214 | 3.17 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | 223 | 224 | org.springframework.boot 225 | spring-boot-maven-plugin 226 | 227 | 228 | 229 | 230 | 231 | 232 | -------------------------------------------------------------------------------- /src/main/java/com/kadoufall/recommender/RecommenderApplication.java: -------------------------------------------------------------------------------- 1 | package com.kadoufall.recommender; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | @SpringBootApplication 7 | public class RecommenderApplication { 8 | 9 | public static void main(String[] args) { 10 | SpringApplication.run(RecommenderApplication.class, args); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/main/java/com/kadoufall/recommender/dao/NewsRepository.java: -------------------------------------------------------------------------------- 1 | package com.kadoufall.recommender.dao; 2 | 3 | import com.kadoufall.recommender.model.News; 4 | import org.springframework.data.domain.Pageable; 5 | import org.springframework.data.jpa.repository.JpaRepository; 6 | import org.springframework.data.jpa.repository.Query; 7 | import org.springframework.data.repository.query.Param; 8 | 9 | import java.util.List; 10 | 11 | public interface NewsRepository extends JpaRepository { 12 | 13 | News findById(long id); 14 | 15 | 16 | 17 | @Query("from News ORDER BY viewNum DESC") 18 | // List findHostestNews(Pageable pageable); 19 | List findHostestNews(); 20 | 21 | 22 | 23 | } -------------------------------------------------------------------------------- /src/main/java/com/kadoufall/recommender/dao/UserOperationRepository.java: -------------------------------------------------------------------------------- 1 | package com.kadoufall.recommender.dao; 2 | 3 | import com.kadoufall.recommender.model.UserOperation; 4 | import org.springframework.data.jpa.repository.JpaRepository; 5 | 6 | import java.util.List; 7 | 8 | public interface UserOperationRepository extends JpaRepository { 9 | 10 | UserOperation findById(long id); 11 | 12 | List findByUserId(long userId); 13 | 14 | } -------------------------------------------------------------------------------- /src/main/java/com/kadoufall/recommender/dao/UserRepository.java: -------------------------------------------------------------------------------- 1 | package com.kadoufall.recommender.dao; 2 | 3 | import com.kadoufall.recommender.model.User; 4 | import org.springframework.data.jpa.repository.JpaRepository; 5 | import org.springframework.data.jpa.repository.Query; 6 | import org.springframework.data.repository.query.Param; 7 | 8 | public interface UserRepository extends JpaRepository { 9 | 10 | User findById(long id); 11 | 12 | 13 | @Query("from User u where u.id=:id") 14 | User findUser(@Param("id") long id); 15 | 16 | 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/com/kadoufall/recommender/dao/UtilRepositoryCustom.java: -------------------------------------------------------------------------------- 1 | package com.kadoufall.recommender.dao; 2 | 3 | import com.kadoufall.recommender.model.News; 4 | import org.springframework.stereotype.Repository; 5 | 6 | import java.sql.Timestamp; 7 | import java.util.List; 8 | 9 | public interface UtilRepositoryCustom { 10 | List findSeenNewsIds(long userId); 11 | 12 | List findSeenNewsIdsBefore(long userId, Timestamp timestamp); 13 | 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/com/kadoufall/recommender/dao/UtilRepositoryImpl.java: -------------------------------------------------------------------------------- 1 | package com.kadoufall.recommender.dao; 2 | 3 | import com.kadoufall.recommender.model.UserOperation; 4 | import org.springframework.beans.factory.annotation.Autowired; 5 | import org.springframework.stereotype.Repository; 6 | 7 | import java.sql.Timestamp; 8 | import java.util.List; 9 | import java.util.stream.Collectors; 10 | 11 | 12 | @Repository 13 | public class UtilRepositoryImpl implements UtilRepositoryCustom { 14 | @Autowired 15 | private UserOperationRepository userOperationRepository; 16 | 17 | 18 | @Override 19 | public List findSeenNewsIds(long userId) { 20 | List userOperations = this.userOperationRepository.findByUserId(userId); 21 | return userOperations.parallelStream().map(UserOperation::getNewsId).collect(Collectors.toList()); 22 | } 23 | 24 | @Override 25 | public List findSeenNewsIdsBefore(long userId, Timestamp timestamp) { 26 | List userOperations = this.userOperationRepository.findByUserId(userId); 27 | return userOperations 28 | .parallelStream() 29 | .filter(u -> u.getReadTime().before(timestamp)) 30 | .map(UserOperation::getNewsId) 31 | .collect(Collectors.toList()); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/main/java/com/kadoufall/recommender/model/News.java: -------------------------------------------------------------------------------- 1 | package com.kadoufall.recommender.model; 2 | 3 | import lombok.Data; 4 | 5 | import javax.persistence.*; 6 | import java.sql.Timestamp; 7 | 8 | @Entity 9 | @Table(name = "news") 10 | @Data 11 | public class News { 12 | @Id 13 | @GeneratedValue(strategy = GenerationType.IDENTITY) 14 | @Column(name = "id") 15 | private long id; 16 | 17 | @Column(name = "title") 18 | private String title; 19 | 20 | @Lob 21 | @Column(name = "passageContent") 22 | private String passageContent; 23 | 24 | @Column(name = "postTime") 25 | private Timestamp postTime; 26 | 27 | @Column(name = "viewNum") 28 | private int viewNum; 29 | 30 | @Column(name = "commentNum") 31 | private int commentNum; 32 | 33 | } 34 | -------------------------------------------------------------------------------- /src/main/java/com/kadoufall/recommender/model/User.java: -------------------------------------------------------------------------------- 1 | package com.kadoufall.recommender.model; 2 | 3 | import lombok.Data; 4 | 5 | import javax.persistence.*; 6 | 7 | @Entity 8 | @Table(name = "user") 9 | @Data 10 | public class User { 11 | @Id 12 | @GeneratedValue(strategy = GenerationType.IDENTITY) 13 | @Column(name = "id") 14 | private long id; 15 | 16 | public User() { 17 | 18 | } 19 | 20 | 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/com/kadoufall/recommender/model/UserOperation.java: -------------------------------------------------------------------------------- 1 | package com.kadoufall.recommender.model; 2 | 3 | import lombok.Data; 4 | import lombok.Getter; 5 | 6 | import javax.persistence.*; 7 | import java.sql.Timestamp; 8 | 9 | @Entity 10 | @Table(name = "userOperation") 11 | @Data 12 | public class UserOperation { 13 | @Id 14 | @GeneratedValue(strategy = GenerationType.IDENTITY) 15 | @Column(name = "id") 16 | private long id; 17 | 18 | @Column(name = "userId") 19 | private long userId; 20 | 21 | @Column(name = "newsId") 22 | private long newsId; 23 | 24 | @Column(name = "readTime") 25 | private Timestamp readTime; 26 | 27 | @Column(name = "preference") 28 | private float preference; 29 | 30 | public UserOperation() { 31 | 32 | } 33 | } 34 | 35 | -------------------------------------------------------------------------------- /src/main/java/com/kadoufall/recommender/service/contentBased/ContentBasedRecommenderService.java: -------------------------------------------------------------------------------- 1 | package com.kadoufall.recommender.service.contentBased; 2 | 3 | import java.util.List; 4 | import java.util.Map; 5 | 6 | public interface ContentBasedRecommenderService { 7 | List recommend(long userId); 8 | 9 | Map evaluate(); 10 | } 11 | -------------------------------------------------------------------------------- /src/main/java/com/kadoufall/recommender/service/contentBased/ContentBasedRecommenderServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.kadoufall.recommender.service.contentBased; 2 | 3 | import com.kadoufall.recommender.dao.UserOperationRepository; 4 | import lombok.extern.log4j.Log4j; 5 | import org.apache.mahout.cf.taste.common.TasteException; 6 | import org.apache.mahout.cf.taste.eval.DataModelBuilder; 7 | import org.apache.mahout.cf.taste.eval.IRStatistics; 8 | import org.apache.mahout.cf.taste.eval.RecommenderBuilder; 9 | import org.apache.mahout.cf.taste.eval.RecommenderIRStatsEvaluator; 10 | import org.apache.mahout.cf.taste.impl.eval.GenericRecommenderIRStatsEvaluator; 11 | import org.apache.mahout.cf.taste.impl.model.GenericBooleanPrefDataModel; 12 | import org.apache.mahout.cf.taste.impl.model.file.FileDataModel; 13 | import org.apache.mahout.cf.taste.impl.model.jdbc.MySQLBooleanPrefJDBCDataModel; 14 | import org.apache.mahout.cf.taste.impl.recommender.GenericBooleanPrefItemBasedRecommender; 15 | import org.apache.mahout.cf.taste.model.DataModel; 16 | import org.apache.mahout.cf.taste.recommender.RecommendedItem; 17 | import org.apache.mahout.cf.taste.recommender.Recommender; 18 | import org.apache.mahout.cf.taste.similarity.ItemSimilarity; 19 | import org.datavec.api.util.ClassPathResource; 20 | import org.deeplearning4j.models.embeddings.loader.WordVectorSerializer; 21 | import org.deeplearning4j.models.paragraphvectors.ParagraphVectors; 22 | import org.deeplearning4j.text.tokenization.tokenizer.preprocessor.CommonPreprocessor; 23 | import org.deeplearning4j.text.tokenization.tokenizerfactory.DefaultTokenizerFactory; 24 | import org.deeplearning4j.text.tokenization.tokenizerfactory.TokenizerFactory; 25 | import org.springframework.beans.factory.annotation.Autowired; 26 | import org.springframework.beans.factory.annotation.Value; 27 | import org.springframework.stereotype.Service; 28 | 29 | import javax.annotation.PostConstruct; 30 | import javax.sql.DataSource; 31 | import java.io.File; 32 | import java.io.FileOutputStream; 33 | import java.io.OutputStreamWriter; 34 | import java.util.*; 35 | import java.util.stream.Collectors; 36 | import java.util.stream.IntStream; 37 | 38 | @Log4j 39 | @Service 40 | public class ContentBasedRecommenderServiceImpl implements ContentBasedRecommenderService { 41 | @Value("${com.kadoufall.mahout.table-name}") 42 | private String tableName; 43 | 44 | @Value("${com.kadoufall.mahout.user-column}") 45 | private String userColumn; 46 | 47 | @Value("${com.kadoufall.mahout.item-column}") 48 | private String itemColumn; 49 | 50 | @Value("${com.kadoufall.mahout.pref-column}") 51 | private String prefColumn; 52 | 53 | @Value("${com.kadoufall.mahout.recommendNum}") 54 | private int recommendNum; 55 | 56 | @Autowired 57 | DataSource dataSource; 58 | 59 | @Autowired 60 | UserOperationRepository userOperationRepository; 61 | 62 | private ParagraphVectors vectors = null; 63 | private DataModel dataModel = null; 64 | private Recommender recommender = null; 65 | 66 | public ContentBasedRecommenderServiceImpl() { 67 | 68 | } 69 | 70 | @PostConstruct 71 | public void init() { 72 | try { 73 | this.dataModel = new MySQLBooleanPrefJDBCDataModel( 74 | dataSource, 75 | this.tableName, 76 | this.userColumn, 77 | this.itemColumn, 78 | this.prefColumn 79 | ); 80 | 81 | // 注意需要先在 TrainVsmModel 中训练 82 | this.initParagraphVectors(); 83 | 84 | // TODO: 移除 dataModel 中过期的用户浏览新闻行为,这些行为对计算用户相似度不再具有较大价值 85 | 86 | ItemSimilarity similarity = new NewsItemSimilarity(this.vectors); 87 | this.recommender = new GenericBooleanPrefItemBasedRecommender(dataModel, similarity); 88 | } catch (Exception e) { 89 | log.error(e.getMessage()); 90 | } 91 | } 92 | 93 | private void initParagraphVectors() throws Exception { 94 | ClassPathResource resource = new ClassPathResource("/model.pv"); 95 | TokenizerFactory t = new DefaultTokenizerFactory(); 96 | t.setTokenPreProcessor(new CommonPreprocessor()); 97 | this.vectors = WordVectorSerializer.readParagraphVectors(resource.getFile()); 98 | vectors.setTokenizerFactory(t); 99 | } 100 | 101 | @Override 102 | public List recommend(long userId) { 103 | List ret = new ArrayList<>(); 104 | 105 | try { 106 | List recommendedItems = recommender.recommend(userId, this.recommendNum); 107 | ret = recommendedItems.parallelStream().map(RecommendedItem::getItemID).collect(Collectors.toList()); 108 | } catch (TasteException e) { 109 | log.error(e.getMessage()); 110 | } 111 | 112 | return ret; 113 | } 114 | 115 | @Override 116 | public Map evaluate() { 117 | RecommenderIRStatsEvaluator evaluator = 118 | new GenericRecommenderIRStatsEvaluator(); 119 | RecommenderBuilder recommenderBuilder = model1 -> { 120 | ItemSimilarity similarity = new NewsItemSimilarity(this.vectors); 121 | return new GenericBooleanPrefItemBasedRecommender(model1, similarity); 122 | }; 123 | DataModelBuilder modelBuilder = trainingData -> new GenericBooleanPrefDataModel( 124 | GenericBooleanPrefDataModel.toDataMap(trainingData)); 125 | 126 | List> all = IntStream.range(1, 2).parallel().boxed().map(i -> { 127 | System.out.println(i); 128 | Map ret = new HashMap<>(16); 129 | 130 | try { 131 | IRStatistics stats = evaluator.evaluate( 132 | recommenderBuilder, modelBuilder, this.dataModel, null, i, 133 | GenericRecommenderIRStatsEvaluator.CHOOSE_THRESHOLD, 134 | 1.0); 135 | 136 | // System.out.println(stats.getPrecision()); 137 | // System.out.println(stats.getRecall()); 138 | // System.out.println(stats.getF1Measure()); 139 | 140 | ret.put("Precision", stats.getPrecision()); 141 | ret.put("Recall", stats.getRecall()); 142 | ret.put("F1Measure", stats.getF1Measure()); 143 | } catch (TasteException e) { 144 | log.error(e.getMessage()); 145 | } 146 | 147 | return ret; 148 | }).collect(Collectors.toList()); 149 | 150 | try { 151 | FileOutputStream fos = new FileOutputStream("src/main/resources/contentBased.txt"); 152 | OutputStreamWriter osw = new OutputStreamWriter(fos, "UTF8"); 153 | 154 | 155 | for (int key = 0; key < all.size(); key++) { 156 | 157 | System.out.println(); 158 | log.info(key + 1); 159 | 160 | double Precision = all.get(key).get("Precision"); 161 | double Recall = all.get(key).get("Recall"); 162 | double F1Measure = all.get(key).get("F1Measure"); 163 | 164 | String write = "|" + String.valueOf(key + 1) + "|" + String.valueOf(Precision) + "|" 165 | + String.valueOf(Recall) + "|" + String.valueOf(F1Measure) + "|" + "\n"; 166 | osw.write(write); 167 | 168 | 169 | for (Map.Entry index : all.get(key).entrySet()) { 170 | log.info(index.getKey() + " " + index.getValue()); 171 | } 172 | 173 | System.out.println(); 174 | } 175 | 176 | 177 | osw.close(); 178 | fos.close(); 179 | } catch (Exception e) { 180 | log.error(e.getMessage()); 181 | } 182 | 183 | return null; 184 | } 185 | 186 | } 187 | -------------------------------------------------------------------------------- /src/main/java/com/kadoufall/recommender/service/contentBased/NewsItemSimilarity.java: -------------------------------------------------------------------------------- 1 | package com.kadoufall.recommender.service.contentBased; 2 | 3 | import com.kadoufall.recommender.service.util.UtilService; 4 | import org.apache.mahout.cf.taste.common.Refreshable; 5 | import org.apache.mahout.cf.taste.common.TasteException; 6 | import org.apache.mahout.cf.taste.similarity.ItemSimilarity; 7 | import org.deeplearning4j.models.paragraphvectors.ParagraphVectors; 8 | import org.springframework.beans.factory.annotation.Autowired; 9 | import org.springframework.http.client.HttpComponentsClientHttpRequestFactory; 10 | import org.springframework.web.client.RestTemplate; 11 | 12 | import java.util.Collection; 13 | 14 | public class NewsItemSimilarity implements ItemSimilarity { 15 | 16 | private ParagraphVectors vectors = null; 17 | 18 | public NewsItemSimilarity(ParagraphVectors vectors) { 19 | this.vectors = vectors; 20 | } 21 | 22 | @Override 23 | public double itemSimilarity(long itemID1, long itemID2) throws TasteException { 24 | double similarity = this.vectors.similarity(String.valueOf(itemID1), String.valueOf(itemID2)); 25 | if (similarity != Double.NaN) { 26 | return similarity; 27 | } 28 | 29 | // TODO: 对model中没有的新闻,推测其向量,再计算相似度 30 | 31 | return 0; 32 | } 33 | 34 | @Override 35 | public double[] itemSimilarities(long itemID1, long[] itemID2s) throws TasteException { 36 | double[] result = new double[itemID2s.length]; 37 | for (int i = 0; i < itemID2s.length; i++) { 38 | result[i] = itemSimilarity(itemID1, itemID2s[i]); 39 | } 40 | 41 | return result; 42 | } 43 | 44 | @Override 45 | public long[] allSimilarItemIDs(long itemID) throws TasteException { 46 | throw new UnsupportedOperationException(); 47 | } 48 | 49 | @Override 50 | public void refresh(Collection alreadyRefreshed) { 51 | 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/main/java/com/kadoufall/recommender/service/contentBased/TrainVsmModel.java: -------------------------------------------------------------------------------- 1 | package com.kadoufall.recommender.service.contentBased; 2 | 3 | import lombok.extern.log4j.Log4j; 4 | import org.datavec.api.util.ClassPathResource; 5 | import org.deeplearning4j.models.embeddings.loader.WordVectorSerializer; 6 | import org.deeplearning4j.models.paragraphvectors.ParagraphVectors; 7 | import org.deeplearning4j.text.documentiterator.LabelAwareIterator; 8 | import org.deeplearning4j.text.documentiterator.LabelledDocument; 9 | import org.deeplearning4j.text.documentiterator.SimpleLabelAwareIterator; 10 | import org.deeplearning4j.text.tokenization.tokenizer.preprocessor.CommonPreprocessor; 11 | import org.deeplearning4j.text.tokenization.tokenizerfactory.DefaultTokenizerFactory; 12 | import org.deeplearning4j.text.tokenization.tokenizerfactory.TokenizerFactory; 13 | import org.nd4j.linalg.api.ndarray.INDArray; 14 | import org.nd4j.linalg.ops.transforms.Transforms; 15 | 16 | import java.io.BufferedReader; 17 | import java.io.FileInputStream; 18 | import java.io.InputStreamReader; 19 | import java.util.ArrayList; 20 | import java.util.List; 21 | 22 | @Log4j 23 | public class TrainVsmModel { 24 | 25 | public static void main(String[] args) { 26 | try { 27 | train(); 28 | // test(); 29 | } catch (Exception e) { 30 | e.printStackTrace(); 31 | } 32 | } 33 | 34 | 35 | private static void train() throws Exception { 36 | List labelledDocumentList = new ArrayList<>(); 37 | List stopwords = new ArrayList<>(); 38 | 39 | FileInputStream fis = new FileInputStream("src/main/resources/caixinWords.txt"); 40 | BufferedReader br = new BufferedReader(new InputStreamReader(fis, "UTF8")); 41 | while (true) { 42 | String line = br.readLine(); 43 | if (line == null) { 44 | break; 45 | } 46 | String[] splitLine = line.trim().split("\t"); 47 | String newsId = splitLine[0]; 48 | String content = splitLine[1]; 49 | 50 | LabelledDocument document = new LabelledDocument(); 51 | document.addLabel(newsId); 52 | document.setContent(content); 53 | labelledDocumentList.add(document); 54 | } 55 | br.close(); 56 | fis.close(); 57 | 58 | 59 | fis = new FileInputStream("src/main/resources/stopword.txt"); 60 | br = new BufferedReader(new InputStreamReader(fis, "UTF8")); 61 | while (true) { 62 | String line = br.readLine(); 63 | if (line == null) { 64 | break; 65 | } 66 | stopwords.add(line.trim()); 67 | } 68 | br.close(); 69 | fis.close(); 70 | 71 | TokenizerFactory tokenizerFactory = new DefaultTokenizerFactory(); 72 | tokenizerFactory.setTokenPreProcessor(new CommonPreprocessor()); 73 | LabelAwareIterator labelAwareIterator = new SimpleLabelAwareIterator(labelledDocumentList); 74 | ParagraphVectors paragraphVectors = new ParagraphVectors.Builder() 75 | .learningRate(0.025) 76 | .minWordFrequency(3) 77 | .minLearningRate(0.001) 78 | .batchSize(1000) 79 | .layerSize(200) 80 | .epochs(70) 81 | .stopWords(stopwords) 82 | .trainSequencesRepresentation(true) 83 | .trainElementsRepresentation(true) 84 | .windowSize(5) 85 | .iterate(labelAwareIterator) 86 | .labelsSource(labelAwareIterator.getLabelsSource()) 87 | .tokenizerFactory(tokenizerFactory) 88 | .build(); 89 | 90 | paragraphVectors.fit(); 91 | 92 | WordVectorSerializer.writeParagraphVectors(paragraphVectors, "src/main/resources/model.pv"); 93 | } 94 | 95 | private static void test() throws Exception { 96 | ClassPathResource resource = new ClassPathResource("/model.pv"); 97 | TokenizerFactory t = new DefaultTokenizerFactory(); 98 | t.setTokenPreProcessor(new CommonPreprocessor()); 99 | ParagraphVectors vectors = WordVectorSerializer.readParagraphVectors(resource.getFile()); 100 | vectors.setTokenizerFactory(t); 101 | 102 | System.out.println(vectors.similarity("100649040", "100648768")); 103 | System.out.println(vectors.similarity("100649040", "100646087")); 104 | System.out.println(vectors.similarity("100649202", "100646120")); 105 | System.out.println(vectors.similarity("100649202", "1")); 106 | 107 | 108 | String str100649040 = "NASA 发布 疑似 马航 航班 失事 地点 高清 地图 美国宇航局 发布 图片 显示 北京 时间 月 日 11 35 NASA 卫星 Terra MODIS 拍摄 相关 海域 一张 250 米 精度 卫星 图像 图片 定位 约 104.6 E 6.1 N 红圈 疑似 马航 370 失事 地点 图片 来源 NASA 网站"; 109 | String str100648768 = "越南 军机 发现 油迹 美国有线电视新闻网 报道 越南 一位 官员 告诉 记者 称 越南 飞机 越南 马来西亚 重叠 水域 表面 发现 疑似 油污 碎片 物体 另据 美联社 华尔街日报 报道 一架 参与 搜救 越南 飞机 马航 客机 疑似 失去 联系 越南 南部 海域 发现 两处 浮油 带 各方 消息 日 凌晨 马航 北京 第二场 发布会 中称 尚 得到 MH370 航班 去向 确实 消息 越南 方面 发现 疑似 飞机 失事 油迹 并未 确认 航班 CFP1"; 110 | String str100646087 = "2014 两会 委员 吃 月 日 北京 政协 经济界 农业 界 委员 驻地 委员 吃 自助餐 用餐 简单 为主 餐品 往年 少 凉菜 三种 水果 两样 肉菜 鸡腿 扣肉 小炒 酒 现场 制作 担担面 糊塌子 江心 CFP1"; 111 | String str100649202 = "官方 称 月 日 天安门 突发事件 已获 处置 人民 公安 报 消息 月 日 十二届 全国人大 二次 会议 开幕 10 时 45 分 北京市公安局 轨道 建设 分局 筹备组 支援 民警 张新 天安门 地区 分局 巡警 二 大队 副大队长 汪 湘江 成功 处置 一起 突发事件 当日 人获 市局 嘉奖 公安部 副 部长 北京 市委常委 公安局 局长 傅政华 随即 颁发 嘉奖 证书 激发 队伍 活力 做好 全国 两会 安保 工作 月 27 日 北京市公安局 启动 战时 党建 战时 表彰 战时 爱警 三 同步 战时 思想 政治 工作 机制 … … 北京市公安局 充分发挥 党建 工作 牵动 引领 组织 保障 作用 切实 党 政治 优势 组织 优势 转化 推动 安保 工作 强大 动力 圆满完成 各项 安保 任务 提供 坚强 组织 保障 党组织 安保 工作 动力源 不到 10 平方米 办公室 每隔 几分钟 一趟 地铁 列车 下面 隧道 驶过 地板 随之 微微 震动 月 日 北京市公安局 公交 总队 前门 站 派出所 前门 站 警务 站 记者 民警 交流 提高 音量 前门 站 地铁 通往 天安门广场 南大门 民警 常年 地铁站 台 守护 平安 充满 噪音 空气 混浊 地下 环境中工作 一天 地下 执勤 值班 10 余个 小时 不见 阳光 民警 保持 高昂 斗志 这是 精神 力量 前门 站 派出所 政委 赵鹏 说 每天 地铁 末班车 晚上 11 点半时 每个 党小组 利用 旅客 少 间隙 当天 勤务 进行 点评 民警 加油 鼓劲 支部 堡垒 小组 一块 阵地 党员 一面 旗帜 全国 两会 安保 期间 北京市 局对 单位 参加 安保 抽调 民警 属地 单位 民警 组成 集体 层层 组建 临时 党支部 党小组 强化 党建 核心作用 今年 市局 特别 设置 党建 微信群 民警 手机 收到 党建 信息 单位 党建 工作 实时 交流 即时 跟进 加强 基层单位 党建 工作 指导 党建 工作 落 每个 民警 身上 做到 岗位 全国 两会 期间 担负 天安门 周边 交通 安保 任务 帅府园 交警大队 每天 负责 勤务 100 民警 早 忙 晚 吃饭 只能 抓住 勤务 间隙 赶紧 扒 几口 月 日 记者 采访 民警 时 只能 见缝插针 地谈 几分钟 天安门 地区 分局 巡警 三 大队 大队长 王东明 休息 间隙 记者 采访 党建 促进 民警 充分发挥 作用 素质 体现 岗位 榜样 党员 民警 最能体现 带动 队伍 战斗力 55 岁 老 党员 天安门 地区 分局 巡警 三 大队 民警 陈晓鲁 膝盖 肿痛 坚守岗位 年轻 民警 父母 年纪 我要 年轻人 带个 好头 工作 做好 王博 高宇 一对 夫妻 北京市公安局 党校 副 科职 青干班 学员 全国 两会 期间 市局 干部 竞争 选拔 工作 要求 党校 安排 天安门 地区 分局 实战 锻炼 月 14 日 开展 巡控 工作 随同 分局 作战 单元 四班 三 运转 一连几天 见不着 面是 常事 自觉 克服困难 不让 分神 高宇 岗位 突发 阑尾炎 特意 同事 瞒 丈夫 不想 分心 影响 工作 一群 默默 岗位 坚守 守护 首都 平安 三个 领导 干部 做 表率 月 日 23 时 东城 分局 巡 特警 支队 民警 王魏峰 终于 提前 下班 班 市局 勤务 指挥部 党委书记 王赤 23 时至 次日 时 勤务 指挥部 32 名 党员 民警 分成 班次 辛苦 值班 一线 民警 替岗 执勤 寒夜 中为 一线 执勤 民警 一班 岗 执 一次 勤 基层 民警 得到 休息 调整 广大 民警 切身感受 市局 党委 关爱 温暖 王赤 说 全国 两会 安保 工作 期间 北京市公安局 组织 全局 两级 党委 第一 党支部 党员 开展 三个 活动 一次 政治动员 一次 替岗 执勤 一次 专题报告 激发 队伍 战斗力 领导 干部 关键 重大 安保 期间 市局 民警 进行 思想 发动 外 还会 安排 专人 带 发现 典型 事例 问题 苗头 双重 任务 采用 政工干部 驻 制 方式 单位 领导 干部 进行 跟进 考察 领导 干部 是否 状态 是否 一线 是否 尽责 今年 全国 两会 期间 市局 采用 24 小时 定时 检查 方式 白天 例行 检查 增加 夜里 巡查 晚上 11 点 出门 检查 多个 单位 往往 回来 凌晨 三四点 一位 考察组 成员 说 单位 一把手 一线 民警 并肩作战 多地 民警 多值 一天 勤 多替 一班 岗 轻伤 火线 丰台 分局 副局长 罗明 今年 全国 两会 前 不慎 摔伤 右手 骨折 面对 安保 任务 分局 领导 罗明 在家 养伤 打着 绷带 石膏 情况 坚守 安保 一线 组织 关爱 外 繁忙 勤务 中 战友 之间 搭 把手 帮个 忙 照应 北京市公安局 单位 发出 战友 替班 岗 倡议书 倡导 民警 分担 工作 树 榜样 激励 民警 争先 创优 全国 两会 安保 期间 市局 每晚 召开 领导 干部 工作 例会 总结 当日 情况 提示 次日 工作 表现 特别 突出 民警 集体 通报 表彰 月 日晚 工作 例会 市局 政治部 代表 党委 西城 分局 月坛 派出所 民警 李云成 通报 表扬 月 日 医院 下达 李云成 母亲 病危 通知 连续 工作 安保 一线 李云成 仅 请假 赶到 医院 母亲 一眼 返回 工作岗位 当天 晚上 10 点多 谢绝 领导 调岗 要求 辛苦 扛 扛 过去 月 日 凌晨 时许 正在 两会 住 巡逻 李云成 接到 爱人 医院 打来 电话 云成 妈 不行 战友 替班 李云成 飞奔 赶往 医院 最终 没能 见 老人 一眼 全国 两会 安保 工作 期间 月坛 派出所 负责 两个 住 安保 任务 两会 安保 任务 外 月坛 派出所 负责 辖区 服务 群众 打击 防范 犯罪 工作 派出所 政委 宋竣 患有 严重 腰椎 疾病 腰里 镶着 钢板 副所长 孟凡旺 患有 腰椎间盘 突出 症 发作 时 疼痛 难忍 袜子 穿 党员 民警 轻伤 火线 实际行动 感染 身边 民警 一个个 平凡 岗位 感人事迹 党建 及时 汇聚 市局 分局 党委 面前 表现 特别 突出 民警 党委 立即 启动 重大 活动 安保 重要 任务 工作 时期 表彰 机制 优秀 民警 获得 表彰 通过考察 机制 重点 考察 党员 发展 对象 及时 举措 鼓舞 民警 士气 激发 队伍 干劲 出现 民警 创先争优 局面 人民 公安 报 记者 丘勋锐 胡 爱华"; 112 | String str100646120 = "天安门广场 安保 全面 升级 月 日 武警 驾驶 敞篷 警车 长安街 巡逻 东方 IC1"; 113 | String str1 = "复旦 大学 计算机 MES APS"; 114 | 115 | 116 | INDArray i1 = vectors.inferVector(str100649040); 117 | INDArray i2 = vectors.inferVector(str100648768); 118 | INDArray i3 = vectors.inferVector(str100646087); 119 | INDArray i4 = vectors.inferVector(str100649202); 120 | INDArray i5 = vectors.inferVector(str100646120); 121 | INDArray i6 = vectors.inferVector(str1); 122 | System.out.println(Transforms.cosineSim(i1, i2)); 123 | System.out.println(Transforms.cosineSim(i1, i3)); 124 | System.out.println(Transforms.cosineSim(i4, i5)); 125 | System.out.println(Transforms.cosineSim(i4, i6)); 126 | } 127 | 128 | 129 | } 130 | -------------------------------------------------------------------------------- /src/main/java/com/kadoufall/recommender/service/hot/HotRecommenderService.java: -------------------------------------------------------------------------------- 1 | package com.kadoufall.recommender.service.hot; 2 | 3 | import com.kadoufall.recommender.model.News; 4 | 5 | import java.util.List; 6 | import java.util.Map; 7 | 8 | public interface HotRecommenderService { 9 | List recommend(long userId); 10 | 11 | List recommendNews(long userId); 12 | Map evaluate(); 13 | 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/com/kadoufall/recommender/service/hot/HotRecommenderServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.kadoufall.recommender.service.hot; 2 | 3 | import com.kadoufall.recommender.dao.NewsRepository; 4 | import com.kadoufall.recommender.dao.UserOperationRepository; 5 | import com.kadoufall.recommender.dao.UtilRepositoryCustom; 6 | import com.kadoufall.recommender.model.News; 7 | import com.kadoufall.recommender.model.UserOperation; 8 | import lombok.extern.log4j.Log4j; 9 | import org.springframework.beans.factory.annotation.Autowired; 10 | import org.springframework.beans.factory.annotation.Value; 11 | import org.springframework.data.domain.PageRequest; 12 | import org.springframework.stereotype.Service; 13 | 14 | import javax.annotation.PostConstruct; 15 | import java.io.FileOutputStream; 16 | import java.io.OutputStreamWriter; 17 | import java.sql.Timestamp; 18 | import java.time.LocalDateTime; 19 | import java.time.format.DateTimeFormatter; 20 | import java.util.ArrayList; 21 | import java.util.HashMap; 22 | import java.util.List; 23 | import java.util.Map; 24 | import java.util.concurrent.ConcurrentHashMap; 25 | import java.util.stream.Collectors; 26 | import java.util.stream.IntStream; 27 | 28 | @Log4j 29 | @Service 30 | public class HotRecommenderServiceImpl implements HotRecommenderService { 31 | 32 | @Value("${com.kadoufall.recommender.recommendNum}") 33 | private int recommendNum; 34 | 35 | @Value("${com.kadoufall.recommender.nowStr}") 36 | private String nowStr; 37 | 38 | @Value("${com.kadoufall.recommender.hotDays}") 39 | private int hotDays; 40 | 41 | private Timestamp beginTime; 42 | 43 | @Autowired 44 | private NewsRepository newsRepository; 45 | 46 | @Autowired 47 | private UtilRepositoryCustom utilRepositoryCustom; 48 | 49 | @Autowired 50 | private UserOperationRepository userOperationRepository; 51 | 52 | private List hottestNews; 53 | 54 | public HotRecommenderServiceImpl() { 55 | 56 | } 57 | 58 | @PostConstruct 59 | public void init() { 60 | // this.hottestNews = this.newsRepository.findHostestNews(PageRequest.of(0, this.recommendNum)); 61 | this.hottestNews = this.newsRepository.findHostestNews(); 62 | 63 | LocalDateTime now = LocalDateTime.parse(this.nowStr, DateTimeFormatter.ofPattern("yyyy.MM.dd_HH:mm:ss")); 64 | this.beginTime = Timestamp.valueOf(now.minusDays(this.hotDays)); 65 | } 66 | 67 | @Override 68 | public List recommend(long userId) { 69 | List seenNews = this.utilRepositoryCustom.findSeenNewsIds(userId); 70 | 71 | return this.hottestNews.stream().filter(news -> { 72 | boolean isOutdated = news.getPostTime().before(this.beginTime); 73 | if (isOutdated) { 74 | return false; 75 | } 76 | boolean seen = seenNews.contains(news.getId()); 77 | return !seen; 78 | }).limit(this.recommendNum).map(News::getId).collect(Collectors.toList()); 79 | } 80 | 81 | @Override 82 | public List recommendNews(long userId) { 83 | 84 | 85 | return this.recommend(userId).parallelStream().map(newsId -> { 86 | return this.newsRepository.findById(newsId.longValue()); 87 | }).collect(Collectors.toList()); 88 | 89 | } 90 | 91 | private List recommendWithNum(long userId, int num) { 92 | List seenNewsAll = this.utilRepositoryCustom.findSeenNewsIdsBefore(userId, this.beginTime); 93 | return this.hottestNews.stream().filter(news -> { 94 | boolean isOutdated = news.getPostTime().before(this.beginTime); 95 | if (isOutdated) { 96 | return false; 97 | } 98 | boolean seen = seenNewsAll.contains(news.getId()); 99 | return !seen; 100 | }).limit(num).map(News::getId).collect(Collectors.toList()); 101 | } 102 | 103 | @Override 104 | public Map evaluate() { 105 | List testUserOperation = this.userOperationRepository.findAll() 106 | .parallelStream() 107 | .filter(userOperation -> userOperation.getReadTime().after(this.beginTime)) 108 | .collect(Collectors.toList()); 109 | 110 | Map> testData = new ConcurrentHashMap<>(); 111 | testUserOperation.parallelStream().forEach(u -> { 112 | long userId = u.getUserId(); 113 | if (testData.containsKey(userId)) { 114 | testData.get(userId).add(u.getNewsId()); 115 | } else { 116 | testData.put(userId, new ArrayList() {{ 117 | this.add(u.getNewsId()); 118 | }}); 119 | } 120 | }); 121 | 122 | 123 | List> all = IntStream.range(1, 31).parallel().boxed().map(i -> { 124 | System.out.println(i); 125 | Map ret = new HashMap<>(16); 126 | 127 | int hit = 0; 128 | int allPrecision = 0; 129 | int allRecall = 0; 130 | 131 | for (Map.Entry> entry : testData.entrySet()) { 132 | long userId = entry.getKey(); 133 | List testNewsIds = entry.getValue(); 134 | 135 | List recommendNewsIds = this.recommendWithNum(userId, i); 136 | 137 | // if (testNewsIds.size() < 5) { 138 | // recommendNewsIds = this.recommendWithNum(userId, 5); 139 | // } else if(testNewsIds.size() < 10) { 140 | // recommendNewsIds = this.recommendWithNum(userId, 10); 141 | // } else if(testNewsIds.size() < 20) { 142 | // recommendNewsIds = this.recommendWithNum(userId, 20); 143 | // } else if(testNewsIds.size() <= 50) { 144 | // recommendNewsIds = this.recommendWithNum(userId, 50); 145 | // } else if(testNewsIds.size() <= 75) { 146 | // recommendNewsIds = this.recommendWithNum(userId, 75); 147 | // } else { 148 | // recommendNewsIds = this.recommendWithNum(userId, 100); 149 | // } 150 | 151 | allPrecision += recommendNewsIds.size(); 152 | allRecall += testNewsIds.size(); 153 | recommendNewsIds.retainAll(testNewsIds); 154 | hit += recommendNewsIds.size(); 155 | } 156 | 157 | double precision = hit * 1.0 / allPrecision; 158 | double recall = hit * 1.0 / allRecall; 159 | double fScore = 2 * recall * precision / ((recall + precision) * 1.0); 160 | 161 | ret.put("Precision", precision); 162 | ret.put("Recall", recall); 163 | ret.put("F1Measure", fScore); 164 | System.out.println(precision + " " + recall + " " + fScore); 165 | return ret; 166 | }).collect(Collectors.toList()); 167 | 168 | try { 169 | FileOutputStream fos = new FileOutputStream("src/main/resources/hot.txt"); 170 | OutputStreamWriter osw = new OutputStreamWriter(fos, "UTF8"); 171 | 172 | 173 | for (int key = 0; key < all.size(); key++) { 174 | 175 | System.out.println(); 176 | log.info(key + 1); 177 | 178 | double Precision = all.get(key).get("Precision"); 179 | double Recall = all.get(key).get("Recall"); 180 | double F1Measure = all.get(key).get("F1Measure"); 181 | 182 | String write = "|" + String.valueOf(key + 1) + "|" + String.valueOf(Precision) + "|" 183 | + String.valueOf(Recall) + "|" + String.valueOf(F1Measure) + "|" + "\n"; 184 | osw.write(write); 185 | 186 | 187 | for (Map.Entry index : all.get(key).entrySet()) { 188 | log.info(index.getKey() + " " + index.getValue()); 189 | } 190 | 191 | System.out.println(); 192 | } 193 | 194 | 195 | osw.close(); 196 | fos.close(); 197 | } catch (Exception e) { 198 | log.error(e.getMessage()); 199 | } 200 | 201 | 202 | return null; 203 | } 204 | 205 | } 206 | -------------------------------------------------------------------------------- /src/main/java/com/kadoufall/recommender/service/userCF/UserCFRecommenderService.java: -------------------------------------------------------------------------------- 1 | package com.kadoufall.recommender.service.userCF; 2 | 3 | import com.kadoufall.recommender.model.News; 4 | 5 | import java.util.List; 6 | import java.util.Map; 7 | 8 | public interface UserCFRecommenderService { 9 | 10 | List recommend(long userId); 11 | 12 | List recommendNews(long userId); 13 | 14 | Map evaluate(int neighborhoodNum, String method); 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/com/kadoufall/recommender/service/userCF/UserCFRecommenderServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.kadoufall.recommender.service.userCF; 2 | 3 | import com.kadoufall.recommender.dao.NewsRepository; 4 | import com.kadoufall.recommender.dao.UserOperationRepository; 5 | import com.kadoufall.recommender.model.News; 6 | import lombok.extern.log4j.Log4j; 7 | import org.apache.mahout.cf.taste.common.TasteException; 8 | import org.apache.mahout.cf.taste.eval.DataModelBuilder; 9 | import org.apache.mahout.cf.taste.eval.IRStatistics; 10 | import org.apache.mahout.cf.taste.eval.RecommenderBuilder; 11 | import org.apache.mahout.cf.taste.eval.RecommenderIRStatsEvaluator; 12 | import org.apache.mahout.cf.taste.impl.eval.GenericRecommenderIRStatsEvaluator; 13 | import org.apache.mahout.cf.taste.impl.model.GenericBooleanPrefDataModel; 14 | import org.apache.mahout.cf.taste.impl.model.file.FileDataModel; 15 | import org.apache.mahout.cf.taste.impl.model.jdbc.MySQLBooleanPrefJDBCDataModel; 16 | import org.apache.mahout.cf.taste.impl.neighborhood.NearestNUserNeighborhood; 17 | import org.apache.mahout.cf.taste.impl.recommender.GenericBooleanPrefUserBasedRecommender; 18 | import org.apache.mahout.cf.taste.impl.similarity.CityBlockSimilarity; 19 | import org.apache.mahout.cf.taste.impl.similarity.LogLikelihoodSimilarity; 20 | import org.apache.mahout.cf.taste.impl.similarity.TanimotoCoefficientSimilarity; 21 | import org.apache.mahout.cf.taste.model.DataModel; 22 | import org.apache.mahout.cf.taste.neighborhood.UserNeighborhood; 23 | import org.apache.mahout.cf.taste.recommender.RecommendedItem; 24 | import org.apache.mahout.cf.taste.recommender.Recommender; 25 | import org.apache.mahout.cf.taste.similarity.UserSimilarity; 26 | import org.springframework.beans.factory.annotation.Autowired; 27 | import org.springframework.beans.factory.annotation.Value; 28 | import org.springframework.stereotype.Service; 29 | 30 | import javax.annotation.PostConstruct; 31 | import javax.sql.DataSource; 32 | import java.io.File; 33 | import java.io.FileOutputStream; 34 | import java.io.OutputStreamWriter; 35 | import java.util.*; 36 | import java.util.stream.Collectors; 37 | import java.util.stream.IntStream; 38 | 39 | @Log4j 40 | @Service 41 | public class UserCFRecommenderServiceImpl implements UserCFRecommenderService { 42 | 43 | @Value("${com.kadoufall.mahout.table-name}") 44 | private String tableName; 45 | 46 | @Value("${com.kadoufall.mahout.user-column}") 47 | private String userColumn; 48 | 49 | @Value("${com.kadoufall.mahout.item-column}") 50 | private String itemColumn; 51 | 52 | @Value("${com.kadoufall.mahout.pref-column}") 53 | private String prefColumn; 54 | 55 | @Value("${com.kadoufall.mahout.recommendNum}") 56 | private int recommendNum; 57 | 58 | @Autowired 59 | DataSource dataSource; 60 | 61 | @Autowired 62 | NewsRepository newsRepository; 63 | 64 | @Autowired 65 | UserOperationRepository userOperationRepository; 66 | 67 | private DataModel dataModel = null; 68 | private Recommender recommender = null; 69 | 70 | public UserCFRecommenderServiceImpl() { 71 | 72 | } 73 | 74 | @PostConstruct 75 | public void init() { 76 | try { 77 | this.dataModel = new MySQLBooleanPrefJDBCDataModel( 78 | dataSource, 79 | this.tableName, 80 | this.userColumn, 81 | this.itemColumn, 82 | this.prefColumn 83 | ); 84 | UserSimilarity similarity = new LogLikelihoodSimilarity(dataModel); 85 | // UserSimilarity similarity = new TanimotoCoefficientSimilarity(dataModel); 86 | // UserSimilarity similarity = new CityBlockSimilarity(dataModel); 87 | UserNeighborhood neighborhood = new NearestNUserNeighborhood(10, similarity, dataModel); 88 | this.recommender = new GenericBooleanPrefUserBasedRecommender(dataModel, neighborhood, similarity); 89 | } catch (Exception e) { 90 | log.error(e.getMessage()); 91 | } 92 | } 93 | 94 | /** 95 | * 评估基于用户的协同过滤推荐 96 | * 97 | * @return map,key为Precision, Recall, F1Measure 98 | */ 99 | @Override 100 | public Map evaluate(int neighborhoodNum, String method) { 101 | // System.setProperty("java.util.concurrent.ForkJoinPool.common.parallelism", "2"); 102 | 103 | RecommenderIRStatsEvaluator evaluator = 104 | new GenericRecommenderIRStatsEvaluator(); 105 | RecommenderBuilder recommenderBuilder = model1 -> { 106 | UserSimilarity similarity = null; 107 | if ("TanimotoCoefficientSimilarity".equals(method)) { 108 | similarity = new TanimotoCoefficientSimilarity(model1); 109 | } else if ("CityBlockSimilarity".equals(method)) { 110 | similarity = new CityBlockSimilarity(model1); 111 | } 112 | // UserSimilarity similarity = new TanimotoCoefficientSimilarity(model1); 113 | // UserSimilarity similarity = new CityBlockSimilarity(model1); 114 | UserNeighborhood neighborhood = 115 | new NearestNUserNeighborhood(neighborhoodNum, similarity, model1); 116 | return new GenericBooleanPrefUserBasedRecommender(model1, neighborhood, similarity); 117 | }; 118 | DataModelBuilder modelBuilder = trainingData -> new GenericBooleanPrefDataModel( 119 | GenericBooleanPrefDataModel.toDataMap(trainingData)); 120 | try { 121 | List> all = IntStream.range(1, 31).parallel().boxed().map(i -> { 122 | System.out.println(i); 123 | Map ret = new HashMap<>(16); 124 | try { 125 | IRStatistics stats = evaluator.evaluate( 126 | recommenderBuilder, modelBuilder, this.dataModel, null, i, 127 | GenericRecommenderIRStatsEvaluator.CHOOSE_THRESHOLD, 128 | 1.0); 129 | 130 | ret.put("Precision", stats.getPrecision()); 131 | ret.put("Recall", stats.getRecall()); 132 | ret.put("F1Measure", stats.getF1Measure()); 133 | } catch (TasteException e) { 134 | log.error(e.getMessage()); 135 | } 136 | 137 | return ret; 138 | }).collect(Collectors.toList()); 139 | 140 | String path = ""; 141 | if ("TanimotoCoefficientSimilarity".equals(method)) { 142 | path = "src/main/resources/Tanimoto-" + String.valueOf(neighborhoodNum) + ".txt"; 143 | } else if ("CityBlockSimilarity".equals(method)) { 144 | path = "src/main/resources/City-" + String.valueOf(neighborhoodNum) + ".txt"; 145 | } 146 | 147 | FileOutputStream fos = new FileOutputStream(path); 148 | OutputStreamWriter osw = new OutputStreamWriter(fos, "UTF8"); 149 | 150 | for (int key = 0; key < all.size(); key++) { 151 | 152 | System.out.println(); 153 | log.info(key + 1); 154 | 155 | double Precision = all.get(key).get("Precision"); 156 | double Recall = all.get(key).get("Recall"); 157 | double F1Measure = all.get(key).get("F1Measure"); 158 | 159 | String write = "|" + String.valueOf(key + 1) + "|" + String.valueOf(Precision) + "|" 160 | + String.valueOf(Recall) + "|" + String.valueOf(F1Measure) + "|" + "\n"; 161 | osw.write(write); 162 | 163 | 164 | for (Map.Entry index : all.get(key).entrySet()) { 165 | log.info(index.getKey() + " " + index.getValue()); 166 | } 167 | 168 | System.out.println(); 169 | } 170 | 171 | 172 | osw.close(); 173 | fos.close(); 174 | } catch (Exception e) { 175 | log.error(e.getMessage()); 176 | } 177 | return null; 178 | } 179 | 180 | /** 181 | * 向用户推荐新闻 182 | * 183 | * @param userId 用户id 184 | * @return 新闻id的list 185 | */ 186 | @Override 187 | public List recommend(long userId) { 188 | List ret = new ArrayList<>(); 189 | 190 | try { 191 | List recommendedItems = recommender.recommend(userId, this.recommendNum); 192 | 193 | Set newsIds = new HashSet<>(); 194 | for (RecommendedItem item : recommendedItems) { 195 | newsIds.add(item.getItemID()); 196 | } 197 | ret.addAll(newsIds); 198 | } catch (TasteException e) { 199 | log.error(e.getMessage()); 200 | } 201 | 202 | return ret; 203 | } 204 | 205 | @Override 206 | public List recommendNews(long userId) { 207 | return this.recommend(userId) 208 | .parallelStream() 209 | .map(newsId -> this.newsRepository.findById(newsId.longValue())) 210 | .collect(Collectors.toList()); 211 | } 212 | 213 | 214 | } 215 | -------------------------------------------------------------------------------- /src/main/java/com/kadoufall/recommender/service/util/UtilService.java: -------------------------------------------------------------------------------- 1 | package com.kadoufall.recommender.service.util; 2 | 3 | public interface UtilService { 4 | 5 | double getSimilarity(long itemID1, long itemID2); 6 | } 7 | -------------------------------------------------------------------------------- /src/main/java/com/kadoufall/recommender/service/util/UtilServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.kadoufall.recommender.service.util; 2 | 3 | import lombok.extern.log4j.Log4j; 4 | import org.apache.http.client.HttpClient; 5 | import org.apache.http.impl.client.DefaultConnectionKeepAliveStrategy; 6 | import org.apache.http.impl.client.DefaultHttpRequestRetryHandler; 7 | import org.apache.http.impl.client.HttpClientBuilder; 8 | import org.apache.http.impl.client.HttpClients; 9 | import org.apache.http.impl.conn.PoolingHttpClientConnectionManager; 10 | import org.springframework.http.client.HttpComponentsClientHttpRequestFactory; 11 | import org.springframework.stereotype.Service; 12 | import org.springframework.web.client.RestTemplate; 13 | 14 | import javax.annotation.PostConstruct; 15 | import java.util.concurrent.TimeUnit; 16 | 17 | @Log4j 18 | //@Service 19 | public class UtilServiceImpl implements UtilService { 20 | 21 | private RestTemplate restTemplate; 22 | 23 | public UtilServiceImpl() { 24 | 25 | } 26 | 27 | @PostConstruct 28 | public void init() { 29 | // 长连接保持30秒 30 | PoolingHttpClientConnectionManager pollingConnectionManager = new PoolingHttpClientConnectionManager(15, TimeUnit.SECONDS); 31 | // 总连接数 32 | pollingConnectionManager.setMaxTotal(1000); 33 | // 同路由的并发数 34 | pollingConnectionManager.setDefaultMaxPerRoute(1000); 35 | 36 | HttpClientBuilder httpClientBuilder = HttpClients.custom(); 37 | httpClientBuilder.setConnectionManager(pollingConnectionManager); 38 | // 重试次数,默认是3次,没有开启 39 | httpClientBuilder.setRetryHandler(new DefaultHttpRequestRetryHandler(2, true)); 40 | // 保持长连接配置,需要在头添加Keep-Alive 41 | httpClientBuilder.setKeepAliveStrategy(new DefaultConnectionKeepAliveStrategy()); 42 | 43 | HttpClient httpClient = httpClientBuilder.build(); 44 | 45 | // httpClient连接配置,底层是配置RequestConfig 46 | HttpComponentsClientHttpRequestFactory clientHttpRequestFactory = new HttpComponentsClientHttpRequestFactory(httpClient); 47 | // 连接超时 48 | clientHttpRequestFactory.setConnectTimeout(5000); 49 | // 数据读取超时时间,即SocketTimeout 50 | clientHttpRequestFactory.setReadTimeout(5000); 51 | // 连接不够用的等待时间,不宜过长,必须设置,比如连接不够用时,时间过长将是灾难性的 52 | clientHttpRequestFactory.setConnectionRequestTimeout(200); 53 | // 缓冲请求数据,默认值是true。通过POST或者PUT大量发送数据时,建议将此属性更改为false,以免耗尽内存。 54 | // clientHttpRequestFactory.setBufferRequestBody(false); 55 | 56 | 57 | this.restTemplate = new RestTemplate(clientHttpRequestFactory); 58 | 59 | } 60 | 61 | 62 | @Override 63 | public double getSimilarity(long itemID1, long itemID2) { 64 | String url = "http://127.0.0.1:5000?newsId1=" + itemID1 + "&newsId2=" + itemID2; 65 | 66 | String ret = this.restTemplate.getForObject(url, String.class); 67 | return ret == null ? 0 : Double.parseDouble(ret); 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /src/main/java/com/kadoufall/recommender/web/RecommendController.java: -------------------------------------------------------------------------------- 1 | package com.kadoufall.recommender.web; 2 | 3 | import com.kadoufall.recommender.dao.NewsRepository; 4 | import com.kadoufall.recommender.model.News; 5 | import com.kadoufall.recommender.service.hot.HotRecommenderService; 6 | import com.kadoufall.recommender.service.userCF.UserCFRecommenderService; 7 | import org.springframework.beans.factory.annotation.Autowired; 8 | import org.springframework.web.bind.annotation.PathVariable; 9 | import org.springframework.web.bind.annotation.RequestMapping; 10 | import org.springframework.web.bind.annotation.RequestMethod; 11 | import org.springframework.web.bind.annotation.RestController; 12 | 13 | import java.util.List; 14 | 15 | @RestController 16 | @RequestMapping(value = "/recommend") 17 | public class RecommendController { 18 | @Autowired 19 | private UserCFRecommenderService userCFRecommenderService; 20 | private HotRecommenderService hotRecommenderService; 21 | private NewsRepository newsRepository; 22 | 23 | @RequestMapping(value = "/", method = RequestMethod.GET) 24 | public String index() { 25 | return "Recommender for Todayim"; 26 | } 27 | 28 | @RequestMapping(value = "/{id}", method = RequestMethod.GET) 29 | public List getRecommendNews(@PathVariable long id) { 30 | return userCFRecommenderService.recommendNews(id); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/main/resources/README.md: -------------------------------------------------------------------------------- 1 | Resources Description 2 | 3 | - log4j.properties 4 | - LOG4J 配置 5 | 6 | - application.properties 7 | - Spring、Hibernate 配置 8 | 9 | - caixinWords.txt 10 | - 新闻分词后的数据, 11 | - 还包括了新闻 ID 12 | 13 | - stopword.txt 14 | - 停用词 15 | 16 | - caixin.base 17 | - 评测 UserCF 时使用的临时本地数据文件 18 | - userId - newsId 19 | - 完整数据在 data 文件夹下 sql 文件中。 20 | 21 | -------------------------------------------------------------------------------- /src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | # datasource 2 | spring.datasource.url=jdbc:mysql://***/caixin?useUnicode=true&characterEncoding=UTF-8 3 | spring.datasource.username=*** 4 | spring.datasource.password=*** 5 | spring.datasource.driver-class-name=com.mysql.jdbc.Driver 6 | 7 | com.kadoufall.mahout.table-name = userOperation 8 | com.kadoufall.mahout.user-column = userId 9 | com.kadoufall.mahout.item-column = newsId 10 | com.kadoufall.mahout.pref-column = preference 11 | com.kadoufall.mahout.recommendNum = 15 12 | 13 | com.kadoufall.recommender.recommendNum = 15 14 | com.kadoufall.recommender.nowStr = 2014.03.31_23:59:59 15 | com.kadoufall.recommender.hotDays = 10 16 | 17 | 18 | # hibernate 19 | spring.jpa.properties.hibernate.hbm2ddl.auto=validate 20 | spring.jpa.show-sql=false 21 | spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.MySQL5Dialect 22 | spring.jpa.hibernate.naming.physical-strategy=org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl 23 | 24 | # console 25 | spring.jackson.serialization.indent_output=true 26 | spring.output.ansi.enabled = DETECT 27 | spring.main.banner-mode=off 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /src/main/resources/log4j.properties: -------------------------------------------------------------------------------- 1 | 2 | # LOG4J配置 3 | log4j.rootCategory=INFO, stdout, file, errorfile 4 | log4j.category.com.kadoufall=DEBUG 5 | 6 | log4j.logger.error=errorfile 7 | 8 | # 控制台输出 9 | log4j.appender.stdout=org.apache.log4j.ConsoleAppender 10 | log4j.appender.stdout.layout=org.apache.log4j.PatternLayout 11 | log4j.appender.stdout.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss,SSS} %5p %c{1}:%L - %m%n 12 | 13 | # root日志输出 14 | log4j.appender.file=org.apache.log4j.DailyRollingFileAppender 15 | log4j.appender.file.file=logs/all.log 16 | log4j.appender.file.DatePattern='.'yyyy-MM-dd 17 | log4j.appender.file.layout=org.apache.log4j.PatternLayout 18 | log4j.appender.file.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss,SSS} %5p %c{1}:%L - %m%n 19 | 20 | # error日志输出 21 | log4j.appender.errorfile=org.apache.log4j.DailyRollingFileAppender 22 | log4j.appender.errorfile.file=logs/error.log 23 | log4j.appender.errorfile.DatePattern='.'yyyy-MM-dd 24 | log4j.appender.errorfile.Threshold = ERROR 25 | log4j.appender.errorfile.layout=org.apache.log4j.PatternLayout 26 | log4j.appender.errorfile.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss,SSS} %5p %c{1}:%L - %m%n 27 | 28 | # com.kadoufall下的日志输出 29 | log4j.appender.kadoufall=org.apache.log4j.DailyRollingFileAppender 30 | log4j.appender.kadoufall.file=logs/my.log 31 | log4j.appender.kadoufall.DatePattern='.'yyyy-MM-dd 32 | log4j.appender.kadoufall.layout=org.apache.log4j.PatternLayout 33 | log4j.appender.kadoufall.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss,SSS} %5p %c{1}:%L ---- %m%n 34 | 35 | log4j.logger.httpclient.wire.header=WARN 36 | log4j.logger.httpclient.wire.content=WARN 37 | 38 | log4j.logger.org.apache.mahout=WARN 39 | 40 | -------------------------------------------------------------------------------- /src/main/resources/stopword.txt: -------------------------------------------------------------------------------- 1 | $ 2 | 0 3 | 1 4 | 2 5 | 3 6 | 4 7 | 5 8 | 6 9 | 7 10 | 8 11 | 9 12 | ? 13 | _ 14 | “ 15 | ” 16 | 、 17 | 。 18 | 《 19 | 》 20 | 一 21 | 一些 22 | 一何 23 | 一切 24 | 一则 25 | 一方面 26 | 一旦 27 | 一来 28 | 一样 29 | 一般 30 | 一转眼 31 | 万一 32 | 上 33 | 上下 34 | 下 35 | 不 36 | 不仅 37 | 不但 38 | 不光 39 | 不单 40 | 不只 41 | 不外乎 42 | 不如 43 | 不妨 44 | 不尽 45 | 不尽然 46 | 不得 47 | 不怕 48 | 不惟 49 | 不成 50 | 不拘 51 | 不料 52 | 不是 53 | 不比 54 | 不然 55 | 不特 56 | 不独 57 | 不管 58 | 不至于 59 | 不若 60 | 不论 61 | 不过 62 | 不问 63 | 与 64 | 与其 65 | 与其说 66 | 与否 67 | 与此同时 68 | 且 69 | 且不说 70 | 且说 71 | 两者 72 | 个 73 | 个别 74 | 临 75 | 为 76 | 为了 77 | 为什么 78 | 为何 79 | 为止 80 | 为此 81 | 为着 82 | 乃 83 | 乃至 84 | 乃至于 85 | 么 86 | 之 87 | 之一 88 | 之所以 89 | 之类 90 | 乌乎 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 | 从此 116 | 从而 117 | 他 118 | 他人 119 | 他们 120 | 以 121 | 以上 122 | 以为 123 | 以便 124 | 以免 125 | 以及 126 | 以故 127 | 以期 128 | 以来 129 | 以至 130 | 以至于 131 | 以致 132 | 们 133 | 任 134 | 任何 135 | 任凭 136 | 似的 137 | 但 138 | 但凡 139 | 但是 140 | 何 141 | 何以 142 | 何况 143 | 何处 144 | 何时 145 | 余外 146 | 作为 147 | 你 148 | 你们 149 | 使 150 | 使得 151 | 例如 152 | 依 153 | 依据 154 | 依照 155 | 便于 156 | 俺 157 | 俺们 158 | 倘 159 | 倘使 160 | 倘或 161 | 倘然 162 | 倘若 163 | 借 164 | 假使 165 | 假如 166 | 假若 167 | 傥然 168 | 像 169 | 儿 170 | 先不先 171 | 光是 172 | 全体 173 | 全部 174 | 兮 175 | 关于 176 | 其 177 | 其一 178 | 其中 179 | 其二 180 | 其他 181 | 其余 182 | 其它 183 | 其次 184 | 具体地说 185 | 具体说来 186 | 兼之 187 | 内 188 | 再 189 | 再其次 190 | 再则 191 | 再有 192 | 再者 193 | 再者说 194 | 再说 195 | 冒 196 | 冲 197 | 况且 198 | 几 199 | 几时 200 | 凡 201 | 凡是 202 | 凭 203 | 凭借 204 | 出于 205 | 出来 206 | 分别 207 | 则 208 | 则甚 209 | 别 210 | 别人 211 | 别处 212 | 别是 213 | 别的 214 | 别管 215 | 别说 216 | 到 217 | 前后 218 | 前此 219 | 前者 220 | 加之 221 | 加以 222 | 即 223 | 即令 224 | 即使 225 | 即便 226 | 即如 227 | 即或 228 | 即若 229 | 却 230 | 去 231 | 又 232 | 又及 233 | 及 234 | 及其 235 | 及至 236 | 反之 237 | 反而 238 | 反过来 239 | 反过来说 240 | 受到 241 | 另 242 | 另一方面 243 | 另外 244 | 另悉 245 | 只 246 | 只当 247 | 只怕 248 | 只是 249 | 只有 250 | 只消 251 | 只要 252 | 只限 253 | 叫 254 | 叮咚 255 | 可 256 | 可以 257 | 可是 258 | 可见 259 | 各 260 | 各个 261 | 各位 262 | 各种 263 | 各自 264 | 同 265 | 同时 266 | 后 267 | 后者 268 | 向 269 | 向使 270 | 向着 271 | 吓 272 | 吗 273 | 否则 274 | 吧 275 | 吧哒 276 | 吱 277 | 呀 278 | 呃 279 | 呕 280 | 呗 281 | 呜 282 | 呜呼 283 | 呢 284 | 呵 285 | 呵呵 286 | 呸 287 | 呼哧 288 | 咋 289 | 和 290 | 咚 291 | 咦 292 | 咧 293 | 咱 294 | 咱们 295 | 咳 296 | 哇 297 | 哈 298 | 哈哈 299 | 哉 300 | 哎 301 | 哎呀 302 | 哎哟 303 | 哗 304 | 哟 305 | 哦 306 | 哩 307 | 哪 308 | 哪个 309 | 哪些 310 | 哪儿 311 | 哪天 312 | 哪年 313 | 哪怕 314 | 哪样 315 | 哪边 316 | 哪里 317 | 哼 318 | 哼唷 319 | 唉 320 | 唯有 321 | 啊 322 | 啐 323 | 啥 324 | 啦 325 | 啪达 326 | 啷当 327 | 喂 328 | 喏 329 | 喔唷 330 | 喽 331 | 嗡 332 | 嗡嗡 333 | 嗬 334 | 嗯 335 | 嗳 336 | 嘎 337 | 嘎登 338 | 嘘 339 | 嘛 340 | 嘻 341 | 嘿 342 | 嘿嘿 343 | 因 344 | 因为 345 | 因了 346 | 因此 347 | 因着 348 | 因而 349 | 固然 350 | 在 351 | 在下 352 | 在于 353 | 地 354 | 基于 355 | 处在 356 | 多 357 | 多么 358 | 多少 359 | 大 360 | 大家 361 | 她 362 | 她们 363 | 好 364 | 如 365 | 如上 366 | 如上所述 367 | 如下 368 | 如何 369 | 如其 370 | 如同 371 | 如是 372 | 如果 373 | 如此 374 | 如若 375 | 始而 376 | 孰料 377 | 孰知 378 | 宁 379 | 宁可 380 | 宁愿 381 | 宁肯 382 | 它 383 | 它们 384 | 对 385 | 对于 386 | 对待 387 | 对方 388 | 对比 389 | 将 390 | 小 391 | 尔 392 | 尔后 393 | 尔尔 394 | 尚且 395 | 就 396 | 就是 397 | 就是了 398 | 就是说 399 | 就算 400 | 就要 401 | 尽 402 | 尽管 403 | 尽管如此 404 | 岂但 405 | 己 406 | 已 407 | 已矣 408 | 巴 409 | 巴巴 410 | 并 411 | 并且 412 | 并非 413 | 庶乎 414 | 庶几 415 | 开外 416 | 开始 417 | 归 418 | 归齐 419 | 当 420 | 当地 421 | 当然 422 | 当着 423 | 彼 424 | 彼时 425 | 彼此 426 | 往 427 | 待 428 | 很 429 | 得 430 | 得了 431 | 怎 432 | 怎么 433 | 怎么办 434 | 怎么样 435 | 怎奈 436 | 怎样 437 | 总之 438 | 总的来看 439 | 总的来说 440 | 总的说来 441 | 总而言之 442 | 恰恰相反 443 | 您 444 | 惟其 445 | 慢说 446 | 我 447 | 我们 448 | 或 449 | 或则 450 | 或是 451 | 或曰 452 | 或者 453 | 截至 454 | 所 455 | 所以 456 | 所在 457 | 所幸 458 | 所有 459 | 才 460 | 才能 461 | 打 462 | 打从 463 | 把 464 | 抑或 465 | 拿 466 | 按 467 | 按照 468 | 换句话说 469 | 换言之 470 | 据 471 | 据此 472 | 接着 473 | 故 474 | 故此 475 | 故而 476 | 旁人 477 | 无 478 | 无宁 479 | 无论 480 | 既 481 | 既往 482 | 既是 483 | 既然 484 | 时候 485 | 是 486 | 是以 487 | 是的 488 | 曾 489 | 替 490 | 替代 491 | 最 492 | 有 493 | 有些 494 | 有关 495 | 有及 496 | 有时 497 | 有的 498 | 望 499 | 朝 500 | 朝着 501 | 本 502 | 本人 503 | 本地 504 | 本着 505 | 本身 506 | 来 507 | 来着 508 | 来自 509 | 来说 510 | 极了 511 | 果然 512 | 果真 513 | 某 514 | 某个 515 | 某些 516 | 某某 517 | 根据 518 | 欤 519 | 正值 520 | 正如 521 | 正巧 522 | 正是 523 | 此 524 | 此地 525 | 此处 526 | 此外 527 | 此时 528 | 此次 529 | 此间 530 | 毋宁 531 | 每 532 | 每当 533 | 比 534 | 比及 535 | 比如 536 | 比方 537 | 没奈何 538 | 沿 539 | 沿着 540 | 漫说 541 | 焉 542 | 然则 543 | 然后 544 | 然而 545 | 照 546 | 照着 547 | 犹且 548 | 犹自 549 | 甚且 550 | 甚么 551 | 甚或 552 | 甚而 553 | 甚至 554 | 甚至于 555 | 用 556 | 用来 557 | 由 558 | 由于 559 | 由是 560 | 由此 561 | 由此可见 562 | 的 563 | 的确 564 | 的话 565 | 直到 566 | 相对而言 567 | 省得 568 | 看 569 | 眨眼 570 | 着 571 | 着呢 572 | 矣 573 | 矣乎 574 | 矣哉 575 | 离 576 | 竟而 577 | 第 578 | 等 579 | 等到 580 | 等等 581 | 简言之 582 | 管 583 | 类如 584 | 紧接着 585 | 纵 586 | 纵令 587 | 纵使 588 | 纵然 589 | 经 590 | 经过 591 | 结果 592 | 给 593 | 继之 594 | 继后 595 | 继而 596 | 综上所述 597 | 罢了 598 | 者 599 | 而 600 | 而且 601 | 而况 602 | 而后 603 | 而外 604 | 而已 605 | 而是 606 | 而言 607 | 能 608 | 能否 609 | 腾 610 | 自 611 | 自个儿 612 | 自从 613 | 自各儿 614 | 自后 615 | 自家 616 | 自己 617 | 自打 618 | 自身 619 | 至 620 | 至于 621 | 至今 622 | 至若 623 | 致 624 | 般的 625 | 若 626 | 若夫 627 | 若是 628 | 若果 629 | 若非 630 | 莫不然 631 | 莫如 632 | 莫若 633 | 虽 634 | 虽则 635 | 虽然 636 | 虽说 637 | 被 638 | 要 639 | 要不 640 | 要不是 641 | 要不然 642 | 要么 643 | 要是 644 | 譬喻 645 | 譬如 646 | 让 647 | 许多 648 | 论 649 | 设使 650 | 设或 651 | 设若 652 | 诚如 653 | 诚然 654 | 该 655 | 说来 656 | 诸 657 | 诸位 658 | 诸如 659 | 谁 660 | 谁人 661 | 谁料 662 | 谁知 663 | 贼死 664 | 赖以 665 | 赶 666 | 起 667 | 起见 668 | 趁 669 | 趁着 670 | 越是 671 | 距 672 | 跟 673 | 较 674 | 较之 675 | 边 676 | 过 677 | 还 678 | 还是 679 | 还有 680 | 还要 681 | 这 682 | 这一来 683 | 这个 684 | 这么 685 | 这么些 686 | 这么样 687 | 这么点儿 688 | 这些 689 | 这会儿 690 | 这儿 691 | 这就是说 692 | 这时 693 | 这样 694 | 这次 695 | 这般 696 | 这边 697 | 这里 698 | 进而 699 | 连 700 | 连同 701 | 逐步 702 | 通过 703 | 遵循 704 | 遵照 705 | 那 706 | 那个 707 | 那么 708 | 那么些 709 | 那么样 710 | 那些 711 | 那会儿 712 | 那儿 713 | 那时 714 | 那样 715 | 那般 716 | 那边 717 | 那里 718 | 都 719 | 鄙人 720 | 鉴于 721 | 针对 722 | 阿 723 | 除 724 | 除了 725 | 除外 726 | 除开 727 | 除此之外 728 | 除非 729 | 随 730 | 随后 731 | 随时 732 | 随着 733 | 难道说 734 | 非但 735 | 非徒 736 | 非特 737 | 非独 738 | 靠 739 | 顺 740 | 顺着 741 | 首先 742 | ! 743 | , 744 | : 745 | ; 746 | ? 747 | 748 | ——— 749 | 》), 750 | )÷(1- 751 | ”, 752 | )、 753 | =( 754 | : 755 | → 756 | ℃ 757 | & 758 | * 759 | 一一 760 | ~~~~ 761 | ’ 762 | . 763 | 『 764 | .一 765 | ./ 766 | -- 767 | 』 768 | =″ 769 | 【 770 | [*] 771 | }> 772 | [⑤]] 773 | [①D] 774 | c] 775 | ng昉 776 | * 777 | // 778 | [ 779 | ] 780 | [②e] 781 | [②g] 782 | ={ 783 | } 784 | ,也 785 | ‘ 786 | A 787 | [①⑥] 788 | [②B] 789 | [①a] 790 | [④a] 791 | [①③] 792 | [③h] 793 | ③] 794 | 1. 795 | -- 796 | [②b] 797 | ’‘ 798 | ××× 799 | [①⑧] 800 | 0:2 801 | =[ 802 | [⑤b] 803 | [②c] 804 | [④b] 805 | [②③] 806 | [③a] 807 | [④c] 808 | [①⑤] 809 | [①⑦] 810 | [①g] 811 | ∈[ 812 | [①⑨] 813 | [①④] 814 | [①c] 815 | [②f] 816 | [②⑧] 817 | [②①] 818 | [①C] 819 | [③c] 820 | [③g] 821 | [②⑤] 822 | [②②] 823 | 一. 824 | [①h] 825 | .数 826 | [] 827 | [①B] 828 | 数/ 829 | [①i] 830 | [③e] 831 | [①①] 832 | [④d] 833 | [④e] 834 | [③b] 835 | [⑤a] 836 | [①A] 837 | [②⑦] 838 | [①d] 839 | [②j] 840 | 〕〔 841 | ][ 842 | :// 843 | ′∈ 844 | [②④ 845 | [⑤e] 846 | 12% 847 | b] 848 | ... 849 | ................... 850 | …………………………………………………③ 851 | ZXFITL 852 | [③F] 853 | 」 854 | [①o] 855 | ]∧′=[ 856 | ∪φ∈ 857 | ′| 858 | {- 859 | ②c 860 | } 861 | [③①] 862 | R.L. 863 | [①E] 864 | Ψ 865 | -[*]- 866 | ↑ 867 | .日 868 | [②d] 869 | [② 870 | [①②] 871 | [②a] 872 | f] 873 | [⑩] 874 | a] 875 | [①e] 876 | [②h] 877 | [②⑥] 878 | [③d] 879 | [②⑩] 880 | e] 881 | 〉 882 | 】 883 | 元/吨 884 | 2.3% 885 | 5:0 886 | [①] 887 | :: 888 | [②] 889 | [③] 890 | [④] 891 | [⑤] 892 | [⑥] 893 | [⑦] 894 | [⑧] 895 | [⑨] 896 | …… 897 | —— 898 | . 899 | , 900 | ' 901 | ? 902 | · 903 | ── 904 | — 905 | < 906 | > 907 | ( 908 | ) 909 | 〔 910 | 〕 911 | [ 912 | ] 913 | ( 914 | ) 915 | - 916 | + 917 | ~ 918 | × 919 | / 920 | / 921 | ① 922 | ② 923 | ③ 924 | ④ 925 | ⑤ 926 | ⑥ 927 | ⑦ 928 | ⑧ 929 | ⑨ 930 | ⑩ 931 | Ⅲ 932 | В 933 | " 934 | ; 935 | # 936 | @ 937 | γ 938 | μ 939 | φ 940 | φ. 941 | × 942 | Δ 943 | ■ 944 | ▲ 945 | sub 946 | exp 947 | sup 948 | Lex 949 | # 950 | % 951 | & 952 | ' 953 | + 954 | +ξ 955 | ++ 956 | - 957 | -β 958 | < 959 | <± 960 | <Δ 961 | <λ 962 | <φ 963 | << 964 | = 965 | = 966 | =☆ 967 | =- 968 | > 969 | >λ 970 | _ 971 | ~± 972 | ~+ 973 | [⑤f] 974 | [⑤d] 975 | [②i] 976 | ≈ 977 | [②G] 978 | [①f] 979 | LI 980 | ㈧ 981 | [- 982 | ...... 983 | [③⑩] 984 | 第二 985 | 一番 986 | 一直 987 | 一个 988 | 种 989 | 有的是 990 | 也就是说 991 | 末##末 992 | 打开天窗说亮话 993 | 到目前为止 994 | 赶早不赶晚 995 | 常言说得好 996 | 何乐而不为 997 | 毫无保留地 998 | 一则通过 999 | 毫无例外 1000 | 不然的话 1001 | 从此以后 1002 | 从古到今 1003 | 从古至今 1004 | 从今以后 1005 | 大张旗鼓 1006 | 从无到有 1007 | 从早到晚 1008 | 弹指之间 1009 | 不亦乐乎 1010 | 不知不觉 1011 | 不止一次 1012 | 不择手段 1013 | 不可开交 1014 | 不可抗拒 1015 | 不仅仅是 1016 | 不管怎样 1017 | 挨家挨户 1018 | 长此下去 1019 | 长话短说 1020 | 除此而外 1021 | 除此以外 1022 | 得天独厚 1023 | 川流不息 1024 | 长期以来 1025 | 挨门挨户 1026 | 挨门逐户 1027 | 多多少少 1028 | 多多益善 1029 | 二话不说 1030 | 更进一步 1031 | 二话没说 1032 | 分期分批 1033 | 风雨无阻 1034 | 归根到底 1035 | 归根结底 1036 | 反之亦然 1037 | 大面儿上 1038 | 倒不如说 1039 | 成年累月 1040 | 或多或少 1041 | 简而言之 1042 | 接连不断 1043 | 尽如人意 1044 | 尽心竭力 1045 | 尽心尽力 1046 | 据我所知 1047 | 具体来说 1048 | 近几年来 1049 | 每时每刻 1050 | 屡次三番 1051 | 三番两次 1052 | 三番五次 1053 | 三天两头 1054 | 老老实实 1055 | 年复一年 1056 | 顷刻之间 1057 | 穷年累月 1058 | 千万千万 1059 | 日复一日 1060 | 如此等等 1061 | 如前所述 1062 | 切不可 1063 | 顷刻间 1064 | 全身心 1065 | 另方面 1066 | 另一个 1067 | 猛然间 1068 | 默默地 1069 | 近年来 1070 | 尽可能 1071 | 接下来 1072 | 急匆匆 1073 | 即是说 1074 | 基本上 1075 | 充其极 1076 | 充其量 1077 | 暗地里 1078 | 反之则 1079 | 比如说 1080 | 背地里 1081 | 背靠背 1082 | 并没有 1083 | 不得不 1084 | 不得了 1085 | 不得已 1086 | 不仅仅 1087 | 不经意 1088 | 不能不 1089 | 不由得 1090 | 不怎么 1091 | 策略地 1092 | 差不多 1093 | 常言道 1094 | 常言说 1095 | 多年来 1096 | 多年前 1097 | 差一点 1098 | 敞开儿 1099 | 抽冷子 1100 | 大不了 1101 | 反倒是 1102 | 大体上 1103 | 当口儿 1104 | 倒不如 1105 | 怪不得 1106 | 动不动 1107 | 看起来 1108 | 看上去 1109 | 看样子 1110 | 够瞧的 1111 | 到了儿 1112 | 呆呆地 1113 | 来不及 1114 | 来得及 1115 | 到头来 1116 | 连日来 1117 | 再次 1118 | 最后 1119 | 您们 1120 | 你是 1121 | 您是 1122 | 我是 1123 | 他是 1124 | 她是 1125 | 它是 1126 | 啊哈 1127 | 啊呀 1128 | 啊哟 1129 | 挨次 1130 | 挨个 1131 | 挨着 1132 | 按理 1133 | 按期 1134 | 默然 1135 | 按时 1136 | 按说 1137 | 暗中 1138 | 暗自 1139 | 昂然 1140 | 八成 1141 | 倍感 1142 | 倍加 1143 | 必定 1144 | 比起 1145 | 比照 1146 | 毕竟 1147 | 必将 1148 | 必须 1149 | 并肩 1150 | 并没 1151 | 并排 1152 | 并无 1153 | 勃然 1154 | 不必 1155 | 不常 1156 | 不大 1157 | 不迭 1158 | 不定 1159 | 不对 1160 | 不会 1161 | 不力 1162 | 不了 1163 | 不满 1164 | 不免 1165 | 不起 1166 | 不巧 1167 | 不日 1168 | 不少 1169 | 不胜 1170 | 不时 1171 | 不同 1172 | 不能 1173 | 不要 1174 | 不外 1175 | 不下 1176 | 不限 1177 | 不消 1178 | 不已 1179 | 不再 1180 | 不曾 1181 | 不止 1182 | 彻夜 1183 | 趁便 1184 | 趁机 1185 | 趁热 1186 | 趁势 1187 | 趁早 1188 | 成心 1189 | 乘机 1190 | 乘势 1191 | 乘隙 1192 | 乘虚 1193 | 迟早 1194 | 充分 1195 | 出去 1196 | 除此 1197 | 除去 1198 | 除却 1199 | 处处 1200 | 传说 1201 | 传闻 1202 | 纯粹 1203 | 此后 1204 | 此中 1205 | 次第 1206 | 匆匆 1207 | 从不 1208 | 从宽 1209 | 从来 1210 | 从轻 1211 | 从速 1212 | 从头 1213 | 从未 1214 | 从小 1215 | 从新 1216 | 从严 1217 | 从优 1218 | 从中 1219 | 从重 1220 | 凑巧 1221 | 存心 1222 | 达旦 1223 | 大大 1224 | 大抵 1225 | 大都 1226 | 大多 1227 | 大凡 1228 | 大概 1229 | 大举 1230 | 大略 1231 | 大约 1232 | 大致 1233 | 待到 1234 | 单纯 1235 | 单单 1236 | 但愿 1237 | 当场 1238 | 当儿 1239 | 当即 1240 | 当庭 1241 | 当头 1242 | 当下 1243 | 当真 1244 | 当中 1245 | 倒是 1246 | 到处 1247 | 到底 1248 | 到头 1249 | 得起 1250 | 顶多 1251 | 动辄 1252 | 陡然 1253 | 独自 1254 | 断然 1255 | 顿时 1256 | 多次 1257 | 多多 1258 | 多亏 1259 | 而论 1260 | 而又 1261 | 尔等 1262 | 反倒 1263 | 反手 1264 | 方才 1265 | 方能 1266 | 非常 1267 | 非得 1268 | 分头 1269 | 奋勇 1270 | 愤然 1271 | 更为 1272 | 更加 1273 | 个人 1274 | 各式 1275 | 刚才 1276 | 敢情 1277 | 该当 1278 | 嘎嘎 1279 | 赶快 1280 | 敢于 1281 | 刚好 1282 | 刚巧 1283 | 高低 1284 | 格外 1285 | 隔日 1286 | 隔夜 1287 | 公然 1288 | 过于 1289 | 共总 1290 | 姑且 1291 | 故意 1292 | 惯常 1293 | 毫不 1294 | 毫无 1295 | 很多 1296 | 何须 1297 | 好在 1298 | 何必 1299 | 何尝 1300 | 何妨 1301 | 何苦 1302 | 何止 1303 | 很少 1304 | 轰然 1305 | 后来 1306 | 呼啦 1307 | 哗啦 1308 | 互相 1309 | 忽地 1310 | 忽然 1311 | 话说 1312 | 伙同 1313 | 豁然 1314 | 恍然 1315 | 或许 1316 | 基本 1317 | 极大 1318 | 极度 1319 | 极端 1320 | 极力 1321 | 极其 1322 | 极为 1323 | 即将 1324 | 即刻 1325 | 几度 1326 | 几番 1327 | 几乎 1328 | 几经 1329 | 加上 1330 | 间或 1331 | 将才 1332 | 简直 1333 | 将近 1334 | 将要 1335 | 交口 1336 | 较比 1337 | 较为 1338 | 皆可 1339 | 截然 1340 | 藉以 1341 | 借此 1342 | 借以 1343 | 届时 1344 | 尽快 1345 | 近来 1346 | 进来 1347 | 进去 1348 | 尽量 1349 | 尽然 1350 | 居然 1351 | 就此 1352 | 就地 1353 | 竟然 1354 | 究竟 1355 | 经常 1356 | 尽早 1357 | 精光 1358 | 局外 1359 | 举凡 1360 | 据称 1361 | 据实 1362 | 据说 1363 | 可好 1364 | 看来 1365 | 绝不 1366 | 决不 1367 | 据悉 1368 | 决非 1369 | 绝顶 1370 | 绝对 1371 | 绝非 1372 | 可能 1373 | 恐怕 1374 | 来讲 1375 | 来看 1376 | 快要 1377 | 拦腰 1378 | 牢牢 1379 | 老是 1380 | 累次 1381 | 累年 1382 | 理当 1383 | 理该 1384 | 理应 1385 | 立地 1386 | 立刻 1387 | 立马 1388 | 立时 1389 | 联袂 1390 | 连连 1391 | 连日 1392 | 路经 1393 | 临到 1394 | 连声 1395 | 连袂 1396 | 另行 1397 | 屡次 1398 | 屡屡 1399 | 缕缕 1400 | 率尔 1401 | 率然 1402 | 略加 1403 | 略微 1404 | 略为 1405 | 论说 1406 | 马上 1407 | 猛然 1408 | 没有 1409 | 每逢 1410 | 每每 1411 | 莫不 1412 | 莫非 1413 | 那末 1414 | 难道 1415 | 难得 1416 | 难怪 1417 | 难说 1418 | 凝神 1419 | 偶而 1420 | 偶尔 1421 | 碰巧 1422 | 偏偏 1423 | 平素 1424 | 迫于 1425 | 扑通 1426 | 其后 1427 | 其实 1428 | 起初 1429 | 起来 1430 | 起首 1431 | 起头 1432 | 起先 1433 | 岂非 1434 | 岂止 1435 | 恰逢 1436 | 恰好 1437 | 恰恰 1438 | 恰巧 1439 | 恰如 1440 | 恰似 1441 | 切莫 1442 | 切切 1443 | 切勿 1444 | 亲口 1445 | 亲身 1446 | 亲手 1447 | 亲眼 1448 | 亲自 1449 | 顷刻 1450 | 请勿 1451 | 取道 1452 | 权时 1453 | 全都 1454 | 全力 1455 | 全年 1456 | 全然 1457 | 人人 1458 | 仍然 1459 | 日见 1460 | 日渐 1461 | 日益 1462 | 日臻 1463 | 如常 1464 | 如次 1465 | 如今 1466 | 如期 1467 | 上来 1468 | 上去 1469 | 瑟瑟 1470 | 沙沙 1471 | 甭 1472 | 会 1473 | 砰 1474 | -- 1475 | ?? 1476 | ???? 1477 | able 1478 | about 1479 | above 1480 | according 1481 | accordingly 1482 | across 1483 | actually 1484 | after 1485 | afterwards 1486 | again 1487 | against 1488 | ain't 1489 | all 1490 | allow 1491 | allows 1492 | almost 1493 | alone 1494 | along 1495 | already 1496 | also 1497 | although 1498 | always 1499 | am 1500 | among 1501 | amongst 1502 | an 1503 | and 1504 | another 1505 | any 1506 | anybody 1507 | anyhow 1508 | anyone 1509 | anything 1510 | anyway 1511 | anyways 1512 | anywhere 1513 | apart 1514 | appear 1515 | appreciate 1516 | appropriate 1517 | are 1518 | aren't 1519 | around 1520 | as 1521 | a's 1522 | aside 1523 | ask 1524 | asking 1525 | associated 1526 | at 1527 | available 1528 | away 1529 | awfully 1530 | be 1531 | became 1532 | because 1533 | become 1534 | becomes 1535 | becoming 1536 | been 1537 | before 1538 | beforehand 1539 | behind 1540 | being 1541 | believe 1542 | below 1543 | beside 1544 | besides 1545 | best 1546 | better 1547 | between 1548 | beyond 1549 | both 1550 | brief 1551 | but 1552 | by 1553 | came 1554 | can 1555 | cannot 1556 | cant 1557 | can't 1558 | cause 1559 | causes 1560 | certain 1561 | certainly 1562 | changes 1563 | clearly 1564 | c'mon 1565 | co 1566 | com 1567 | come 1568 | comes 1569 | concerning 1570 | consequently 1571 | consider 1572 | considering 1573 | contain 1574 | containing 1575 | contains 1576 | corresponding 1577 | could 1578 | couldn't 1579 | course 1580 | c's 1581 | currently 1582 | definitely 1583 | described 1584 | despite 1585 | did 1586 | didn't 1587 | different 1588 | do 1589 | does 1590 | doesn't 1591 | doing 1592 | done 1593 | don't 1594 | down 1595 | downwards 1596 | during 1597 | each 1598 | edu 1599 | eg 1600 | eight 1601 | either 1602 | else 1603 | elsewhere 1604 | enough 1605 | entirely 1606 | especially 1607 | et 1608 | etc 1609 | even 1610 | ever 1611 | every 1612 | everybody 1613 | everyone 1614 | everything 1615 | everywhere 1616 | ex 1617 | exactly 1618 | example 1619 | except 1620 | far 1621 | few 1622 | fifth 1623 | first 1624 | five 1625 | followed 1626 | following 1627 | follows 1628 | for 1629 | former 1630 | formerly 1631 | forth 1632 | four 1633 | from 1634 | further 1635 | furthermore 1636 | get 1637 | gets 1638 | getting 1639 | given 1640 | gives 1641 | go 1642 | goes 1643 | going 1644 | gone 1645 | got 1646 | gotten 1647 | greetings 1648 | had 1649 | hadn't 1650 | happens 1651 | hardly 1652 | has 1653 | hasn't 1654 | have 1655 | haven't 1656 | having 1657 | he 1658 | hello 1659 | help 1660 | hence 1661 | her 1662 | here 1663 | hereafter 1664 | hereby 1665 | herein 1666 | here's 1667 | hereupon 1668 | hers 1669 | herself 1670 | he's 1671 | hi 1672 | him 1673 | himself 1674 | his 1675 | hither 1676 | hopefully 1677 | how 1678 | howbeit 1679 | however 1680 | i'd 1681 | ie 1682 | if 1683 | ignored 1684 | i'll 1685 | i'm 1686 | immediate 1687 | in 1688 | inasmuch 1689 | inc 1690 | indeed 1691 | indicate 1692 | indicated 1693 | indicates 1694 | inner 1695 | insofar 1696 | instead 1697 | into 1698 | inward 1699 | is 1700 | isn't 1701 | it 1702 | it'd 1703 | it'll 1704 | its 1705 | it's 1706 | itself 1707 | i've 1708 | just 1709 | keep 1710 | keeps 1711 | kept 1712 | know 1713 | known 1714 | knows 1715 | last 1716 | lately 1717 | later 1718 | latter 1719 | latterly 1720 | least 1721 | less 1722 | lest 1723 | let 1724 | let's 1725 | like 1726 | liked 1727 | likely 1728 | little 1729 | look 1730 | looking 1731 | looks 1732 | ltd 1733 | mainly 1734 | many 1735 | may 1736 | maybe 1737 | me 1738 | mean 1739 | meanwhile 1740 | merely 1741 | might 1742 | more 1743 | moreover 1744 | most 1745 | mostly 1746 | much 1747 | must 1748 | my 1749 | myself 1750 | name 1751 | namely 1752 | nd 1753 | near 1754 | nearly 1755 | necessary 1756 | need 1757 | needs 1758 | neither 1759 | never 1760 | nevertheless 1761 | new 1762 | next 1763 | nine 1764 | no 1765 | nobody 1766 | non 1767 | none 1768 | noone 1769 | nor 1770 | normally 1771 | not 1772 | nothing 1773 | novel 1774 | now 1775 | nowhere 1776 | obviously 1777 | of 1778 | off 1779 | often 1780 | oh 1781 | ok 1782 | okay 1783 | old 1784 | on 1785 | once 1786 | one 1787 | ones 1788 | only 1789 | onto 1790 | or 1791 | other 1792 | others 1793 | otherwise 1794 | ought 1795 | our 1796 | ours 1797 | ourselves 1798 | out 1799 | outside 1800 | over 1801 | overall 1802 | own 1803 | particular 1804 | particularly 1805 | per 1806 | perhaps 1807 | placed 1808 | please 1809 | plus 1810 | possible 1811 | presumably 1812 | probably 1813 | provides 1814 | que 1815 | quite 1816 | qv 1817 | rather 1818 | rd 1819 | re 1820 | really 1821 | reasonably 1822 | regarding 1823 | regardless 1824 | regards 1825 | relatively 1826 | respectively 1827 | right 1828 | said 1829 | same 1830 | saw 1831 | say 1832 | saying 1833 | says 1834 | second 1835 | secondly 1836 | see 1837 | seeing 1838 | seem 1839 | seemed 1840 | seeming 1841 | seems 1842 | seen 1843 | self 1844 | selves 1845 | sensible 1846 | sent 1847 | serious 1848 | seriously 1849 | seven 1850 | several 1851 | shall 1852 | she 1853 | should 1854 | shouldn't 1855 | since 1856 | six 1857 | so 1858 | some 1859 | somebody 1860 | somehow 1861 | someone 1862 | something 1863 | sometime 1864 | sometimes 1865 | somewhat 1866 | somewhere 1867 | soon 1868 | sorry 1869 | specified 1870 | specify 1871 | specifying 1872 | still 1873 | such 1874 | sure 1875 | take 1876 | taken 1877 | tell 1878 | tends 1879 | th 1880 | than 1881 | thank 1882 | thanks 1883 | thanx 1884 | that 1885 | thats 1886 | that's 1887 | the 1888 | their 1889 | theirs 1890 | them 1891 | themselves 1892 | then 1893 | thence 1894 | there 1895 | thereafter 1896 | thereby 1897 | therefore 1898 | therein 1899 | theres 1900 | there's 1901 | thereupon 1902 | these 1903 | they 1904 | they'd 1905 | they'll 1906 | they're 1907 | they've 1908 | think 1909 | third 1910 | this 1911 | thorough 1912 | thoroughly 1913 | those 1914 | though 1915 | three 1916 | through 1917 | throughout 1918 | thru 1919 | thus 1920 | to 1921 | together 1922 | too 1923 | took 1924 | toward 1925 | towards 1926 | tried 1927 | tries 1928 | truly 1929 | try 1930 | trying 1931 | t's 1932 | twice 1933 | two 1934 | un 1935 | under 1936 | unfortunately 1937 | unless 1938 | unlikely 1939 | until 1940 | unto 1941 | up 1942 | upon 1943 | us 1944 | use 1945 | used 1946 | useful 1947 | uses 1948 | using 1949 | usually 1950 | value 1951 | various 1952 | very 1953 | via 1954 | viz 1955 | vs 1956 | want 1957 | wants 1958 | was 1959 | wasn't 1960 | way 1961 | we 1962 | we'd 1963 | welcome 1964 | well 1965 | we'll 1966 | went 1967 | were 1968 | we're 1969 | weren't 1970 | we've 1971 | what 1972 | whatever 1973 | what's 1974 | when 1975 | whence 1976 | whenever 1977 | where 1978 | whereafter 1979 | whereas 1980 | whereby 1981 | wherein 1982 | where's 1983 | whereupon 1984 | wherever 1985 | whether 1986 | which 1987 | while 1988 | whither 1989 | who 1990 | whoever 1991 | whole 1992 | whom 1993 | who's 1994 | whose 1995 | why 1996 | will 1997 | willing 1998 | wish 1999 | with 2000 | within 2001 | without 2002 | wonder 2003 | won't 2004 | would 2005 | wouldn't 2006 | yes 2007 | yet 2008 | you 2009 | you'd 2010 | you'll 2011 | your 2012 | you're 2013 | yours 2014 | yourself 2015 | yourselves 2016 | you've 2017 | zero 2018 | zt 2019 | ZT 2020 | zz 2021 | ZZ 2022 | һ 2023 | һ? 2024 | һЩ 2025 | һ?? 2026 | һ??? 2027 | һʱ 2028 | һƬ 2029 | һֱ 2030 | ?һ 2031 | ?ȥ 2032 | ??? 2033 | ??һ 2034 | ??ֻ 2035 | ??ͬ 2036 | ??Ω 2037 | ??Ȼ 2038 | ??Ҫ 2039 | ????ʱ 2040 | ר? 2041 | 丨 2042 | " 2043 | | 2044 | ◆ 2045 | ∣ 2046 | ﹝ 2047 | ﹞ -------------------------------------------------------------------------------- /src/test/java/com/kadoufall/recommender/RecommenderApplicationTests.java: -------------------------------------------------------------------------------- 1 | package com.kadoufall.recommender; 2 | 3 | import org.junit.Test; 4 | import org.junit.runner.RunWith; 5 | import org.springframework.boot.test.context.SpringBootTest; 6 | import org.springframework.test.context.junit4.SpringRunner; 7 | 8 | @RunWith(SpringRunner.class) 9 | @SpringBootTest 10 | public class RecommenderApplicationTests { 11 | 12 | @Test 13 | public void contextLoads() { 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /src/test/java/com/kadoufall/recommender/dao/DomainTest.java: -------------------------------------------------------------------------------- 1 | package com.kadoufall.recommender.dao; 2 | 3 | import com.kadoufall.recommender.model.News; 4 | import com.kadoufall.recommender.model.User; 5 | import com.kadoufall.recommender.model.UserOperation; 6 | import org.junit.Test; 7 | import org.junit.runner.RunWith; 8 | import org.springframework.beans.factory.annotation.Autowired; 9 | import org.springframework.boot.test.context.SpringBootTest; 10 | import org.springframework.test.context.junit4.SpringRunner; 11 | 12 | import java.util.List; 13 | 14 | @RunWith(SpringRunner.class) 15 | @SpringBootTest 16 | public class DomainTest { 17 | @Autowired 18 | private UserRepository userRepository; 19 | 20 | @Autowired 21 | private NewsRepository newsRepository; 22 | 23 | @Autowired 24 | private UserOperationRepository userOperationRepository; 25 | 26 | @Test 27 | public void testUser() throws Exception { 28 | 29 | List users = userRepository.findAll(); 30 | for (User user:users) { 31 | System.out.println(user.getId()); 32 | } 33 | } 34 | 35 | @Test 36 | public void testNews() throws Exception { 37 | List newsList = newsRepository.findAll(); 38 | for (News news:newsList) { 39 | System.out.println(news.getId() + " " + news.getTitle() + " " + news.getPostTime()); 40 | } 41 | 42 | } 43 | 44 | @Test 45 | public void testUserOperation() throws Exception { 46 | List userOperations = userOperationRepository.findAll(); 47 | 48 | for (UserOperation useroperation:userOperations) { 49 | System.out.println(useroperation.getId() +" " + useroperation.getNewsId() + " " 50 | + useroperation.getUserId() + " " + useroperation.getReadTime()); 51 | } 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/test/java/com/kadoufall/recommender/recommender/EvaluateTest.java: -------------------------------------------------------------------------------- 1 | package com.kadoufall.recommender.recommender; 2 | 3 | import org.apache.mahout.cf.taste.eval.DataModelBuilder; 4 | import org.apache.mahout.cf.taste.eval.IRStatistics; 5 | import org.apache.mahout.cf.taste.eval.RecommenderBuilder; 6 | import org.apache.mahout.cf.taste.eval.RecommenderIRStatsEvaluator; 7 | import org.apache.mahout.cf.taste.impl.eval.GenericRecommenderIRStatsEvaluator; 8 | import org.apache.mahout.cf.taste.impl.model.GenericBooleanPrefDataModel; 9 | import org.apache.mahout.cf.taste.impl.model.file.FileDataModel; 10 | import org.apache.mahout.cf.taste.impl.neighborhood.NearestNUserNeighborhood; 11 | import org.apache.mahout.cf.taste.impl.recommender.GenericBooleanPrefUserBasedRecommender; 12 | import org.apache.mahout.cf.taste.impl.similarity.LogLikelihoodSimilarity; 13 | import org.apache.mahout.cf.taste.model.DataModel; 14 | import org.apache.mahout.cf.taste.neighborhood.UserNeighborhood; 15 | import org.apache.mahout.cf.taste.similarity.UserSimilarity; 16 | import org.junit.Test; 17 | import org.junit.runner.RunWith; 18 | import org.springframework.boot.test.context.SpringBootTest; 19 | import org.springframework.test.context.junit4.SpringRunner; 20 | 21 | import java.io.File; 22 | 23 | @RunWith(SpringRunner.class) 24 | @SpringBootTest 25 | public class EvaluateTest { 26 | @Test 27 | public void testUserCF() throws Exception { 28 | DataModel model = new GenericBooleanPrefDataModel( 29 | GenericBooleanPrefDataModel.toDataMap( 30 | new FileDataModel(new File("src/main/resources/caixin.base")))); 31 | 32 | RecommenderIRStatsEvaluator evaluator = 33 | new GenericRecommenderIRStatsEvaluator(); 34 | // UserSimilarity similarity = new TanimotoCoefficientSimilarity(com.kadoufall.model); 35 | UserSimilarity similarity = new LogLikelihoodSimilarity(model); 36 | UserNeighborhood neighborhood = 37 | new NearestNUserNeighborhood(10, similarity, model); 38 | RecommenderBuilder recommenderBuilder = model1 -> { 39 | return new GenericBooleanPrefUserBasedRecommender(model1, neighborhood, similarity); 40 | }; 41 | DataModelBuilder modelBuilder = trainingData -> new GenericBooleanPrefDataModel( 42 | GenericBooleanPrefDataModel.toDataMap(trainingData)); 43 | IRStatistics stats = evaluator.evaluate( 44 | recommenderBuilder, modelBuilder, model, null, 10, 45 | GenericRecommenderIRStatsEvaluator.CHOOSE_THRESHOLD, 46 | 1.0); 47 | System.out.println(stats.getPrecision()); 48 | System.out.println(stats.getRecall()); 49 | System.out.println(stats.getF1Measure()); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/test/java/com/kadoufall/recommender/recommender/MahoutTest.java: -------------------------------------------------------------------------------- 1 | package com.kadoufall.recommender.recommender; 2 | 3 | import com.kadoufall.recommender.service.userCF.UserCFRecommenderService; 4 | import com.kadoufall.recommender.service.contentBased.NewsItemSimilarity; 5 | import org.apache.mahout.cf.taste.impl.model.jdbc.MySQLBooleanPrefJDBCDataModel; 6 | import org.apache.mahout.cf.taste.impl.neighborhood.NearestNUserNeighborhood; 7 | import org.apache.mahout.cf.taste.impl.recommender.GenericBooleanPrefItemBasedRecommender; 8 | import org.apache.mahout.cf.taste.impl.recommender.GenericBooleanPrefUserBasedRecommender; 9 | import org.apache.mahout.cf.taste.impl.similarity.LogLikelihoodSimilarity; 10 | import org.apache.mahout.cf.taste.model.DataModel; 11 | import org.apache.mahout.cf.taste.neighborhood.UserNeighborhood; 12 | import org.apache.mahout.cf.taste.recommender.Recommender; 13 | import org.apache.mahout.cf.taste.similarity.ItemSimilarity; 14 | import org.apache.mahout.cf.taste.similarity.UserSimilarity; 15 | import org.deeplearning4j.models.embeddings.loader.WordVectorSerializer; 16 | import org.deeplearning4j.models.paragraphvectors.ParagraphVectors; 17 | import org.deeplearning4j.text.tokenization.tokenizer.preprocessor.CommonPreprocessor; 18 | import org.deeplearning4j.text.tokenization.tokenizerfactory.DefaultTokenizerFactory; 19 | import org.deeplearning4j.text.tokenization.tokenizerfactory.TokenizerFactory; 20 | import org.junit.Test; 21 | import org.junit.runner.RunWith; 22 | import org.springframework.beans.factory.annotation.Autowired; 23 | import org.springframework.boot.test.context.SpringBootTest; 24 | import org.springframework.test.context.junit4.SpringRunner; 25 | 26 | import javax.sql.DataSource; 27 | import java.io.PrintWriter; 28 | import java.sql.Connection; 29 | import java.sql.SQLException; 30 | import java.sql.SQLFeatureNotSupportedException; 31 | import java.util.Map; 32 | import java.util.concurrent.Executor; 33 | import java.util.concurrent.ExecutorService; 34 | import java.util.concurrent.locks.Lock; 35 | import java.util.concurrent.locks.ReentrantLock; 36 | import java.util.logging.Logger; 37 | 38 | @RunWith(SpringRunner.class) 39 | @SpringBootTest 40 | public class MahoutTest { 41 | 42 | @Autowired 43 | private UserCFRecommenderService userCFRecommenderService; 44 | 45 | @Test 46 | public void testUserCF() throws Exception { 47 | for (int i = 5; i <= 30; i += 5) { 48 | if (i == 10) { 49 | continue; 50 | } 51 | userCFRecommenderService.evaluate(i, "TanimotoCoefficientSimilarity"); 52 | } 53 | 54 | for (int i = 5; i <= 30; i += 5) { 55 | if (i == 10) { 56 | continue; 57 | } 58 | userCFRecommenderService.evaluate(i, "CityBlockSimilarity"); 59 | } 60 | 61 | 62 | // Map result = userCFRecommenderService.evaluate(10); 63 | 64 | // for (Map.Entry entry : result.entrySet()) { 65 | // System.out.println(entry.getKey() + " " + entry.getValue()); 66 | // } 67 | } 68 | 69 | } 70 | -------------------------------------------------------------------------------- /src/test/java/com/kadoufall/recommender/service/ContentBasedRecommenderServiceTest.java: -------------------------------------------------------------------------------- 1 | package com.kadoufall.recommender.service; 2 | 3 | import com.kadoufall.recommender.service.contentBased.ContentBasedRecommenderService; 4 | import org.junit.Test; 5 | import org.junit.runner.RunWith; 6 | import org.springframework.beans.factory.annotation.Autowired; 7 | import org.springframework.boot.test.context.SpringBootTest; 8 | import org.springframework.test.context.junit4.SpringRunner; 9 | 10 | @RunWith(SpringRunner.class) 11 | @SpringBootTest 12 | public class ContentBasedRecommenderServiceTest { 13 | @Autowired 14 | ContentBasedRecommenderService contentBasedRecommenderService; 15 | 16 | @Test 17 | public void testHotNum() throws Exception { 18 | this.contentBasedRecommenderService.evaluate(); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/test/java/com/kadoufall/recommender/service/HotRecommenderServiceTest.java: -------------------------------------------------------------------------------- 1 | package com.kadoufall.recommender.service; 2 | 3 | import com.kadoufall.recommender.service.hot.HotRecommenderService; 4 | import org.junit.Test; 5 | import org.junit.runner.RunWith; 6 | import org.springframework.beans.factory.annotation.Autowired; 7 | import org.springframework.boot.test.context.SpringBootTest; 8 | import org.springframework.test.context.junit4.SpringRunner; 9 | 10 | @RunWith(SpringRunner.class) 11 | @SpringBootTest 12 | public class HotRecommenderServiceTest { 13 | @Autowired 14 | HotRecommenderService hotRecommenderService; 15 | 16 | @Test 17 | public void testHotNum() throws Exception { 18 | // this.hotRecommenderService.recommend(5218791); 19 | // this.hotRecommenderService.evaluate(); 20 | } 21 | 22 | } 23 | --------------------------------------------------------------------------------