ホームページ >Java >&#&チュートリアル >Java を使用してレコメンデーション システム ベースのソーシャル ネットワーク アプリケーションを作成する方法

Java を使用してレコメンデーション システム ベースのソーシャル ネットワーク アプリケーションを作成する方法

WBOY
WBOYオリジナル
2023-06-27 08:32:141199ブラウズ

現代のソーシャル ネットワーク アプリケーションでは、レコメンデーション システムが不可欠な機能になっています。ユーザーに友達を勧めたり、興味のあるトピックを勧めたり、関連製品を勧めたり、より価値のあるコンテンツを勧めたりする場合でも、レコメンデーション システムはユーザー エクスペリエンスと継続性を効果的に向上させることができます。

この記事では、Java を使用してレコメンデーション システムに基づいたソーシャル ネットワーク アプリケーションを作成する方法を紹介します。実際のコードと詳細な手順を組み合わせて、読者が基本的なレコメンデーション システムをすぐに理解して実装できるようにします。

1. データの収集と処理

レコメンデーション システムを実装する前に、大量のデータを収集して処理する必要があります。ソーシャル ネットワーク アプリケーションでは、ユーザー情報、投稿、コメント、いいね! などのデータはすべて貴重なデータ ソースです。

デモンストレーションを容易にするために、オープンソースの仮想データ ジェネレーターを使用してこれらのデータを生成できます。具体的な手順は次のとおりです。

  1. Mockaroo (https://www.mockaroo.com/) などの仮想データ ジェネレーターをダウンロードしてインストールします。
  2. ユーザー情報、投稿、コメントなど、生成する必要があるデータセットを定義します。
  3. データを生成し、CSV ファイルにエクスポートします。
  4. Java コードを使用して、CSV ファイル内のデータを読み取り、データベースに保存します。 MySQL や Oracle などの一般的なリレーショナル データベースを使用してデータを保存できます。ここでは、データ保存用のデータベースとして MySQL 8.0 を使用します。

2. ユーザーとアイテムの表現

レコメンデーション システムでは、ユーザーとアイテムの類似性を計算したり、レコメンデーションを作成したりするために、ユーザーとアイテムをベクトルまたは行列形式に変換する必要があります。ソーシャル ネットワーク アプリケーションでは、次のメソッドを使用してユーザーとアイテムを表すことができます:

  1. ユーザー ベクトル: ユーザーがフォローしているトピック、公開する投稿、やり取りする友人などのデータを使用できます。ユーザーのベクトル。たとえば、ユーザー A が Java、Python、JavaScript などのトピックをフォローし、「Java を上手に学ぶ方法」および「Java 入門」を投稿し、ユーザー B および C と対話する場合、次のベクトルを使用できます。ユーザー A を表す場合:

ユーザー A = [1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0 , 0, 1, 0, 0, 1]

ベクトルの長さは 24 で、各位置はトピックまたは投稿を表します。 1 はユーザー A がトピックをフォローしたか、投稿を公開したことを意味し、0 はフォローしていないことを意味します。

  1. アイテム ベクトル: 各投稿のタグ、コンテンツ、コメント、その他のデータを使用して、投稿のベクトルを表すことができます。たとえば、投稿に「Java、プログラミング」というタグが付けられ、内容が「Java プログラミングを学習するための 4 つの提案」で 10 件のコメントがある場合、次のベクトルを使用して投稿を表すことができます。 #Post A = [1, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10 , 0]
ベクトルの長さは 24 で、各位置はラベルまたは統計データを表します。 1 は投稿にタグまたはコンテンツが含まれていることを意味し、0 は含まれていないことを意味します。

3. ユーザーベースの協調フィルタリングの推奨

ユーザーベースの協調フィルタリングは、推奨システムの一般的な方法であり、ユーザーの関心の類似性に基づいてアイテムを推奨します。ここでは、ユーザーベースの協調フィルタリングを使用して、ユーザーに適切な投稿を推奨します。具体的な手順は次のとおりです。

ユーザー間の類似性を計算します。ここでは、類似性メトリックとしてピアソン相関係数を使用します。

    ターゲット ユーザーとの関心の類似性が最も高い K 人のユーザーを選択します。
  1. 各ユーザーについて、気に入っているが対象ユーザーには見られていない投稿を N 個選択します。
  2. 選択した N 個の投稿について、各投稿の推奨スコアを計算し、高いものから低いものへ並べ替えます。
  3. スコアが最も高い上位 M 個の投稿を推奨結果として選択します。
  4. 次は、アルゴリズムの Java コード実装です:
  5. public class CollaborativeFiltering {
    
        /**
         * 计算用户间的皮尔逊相关系数
         * @param user1 用户1
         * @param user2 用户2
         * @param data 数据集
         * @return 皮尔逊相关系数
         */
        public double pearsonCorrelation(Map<Integer, Double> user1, Map<Integer, Double> user2,
                                          Map<Integer, Map<Integer, Double>> data) {
            double sum1 = 0, sum2 = 0, sum1Sq = 0, sum2Sq = 0, pSum = 0;
            int n = 0;
            for (int item : user1.keySet()) {
                if (user2.containsKey(item)) {
                    sum1 += user1.get(item);
                    sum2 += user2.get(item);
                    sum1Sq += Math.pow(user1.get(item), 2);
                    sum2Sq += Math.pow(user2.get(item), 2);
                    pSum += user1.get(item) * user2.get(item);
                    n++;
                }
            }
            if (n == 0)
                return 0;
            double num = pSum - (sum1 * sum2 / n);
            double den = Math.sqrt((sum1Sq - Math.pow(sum1, 2) / n) *
                    (sum2Sq - Math.pow(sum2, 2) / n));
            if (den == 0)
                return 0;
            return num / den;
        }
    
        /**
         * 基于用户的协同过滤推荐算法
         * @param data 数据集
         * @param userId 目标用户 ID
         * @param K 最相似的 K 个用户
         * @param N 推荐的 N 个帖子
         * @return 推荐的帖子 ID 列表
         */
        public List<Integer> userBasedCollaborativeFiltering(Map<Integer, Map<Integer, Double>> data,
                                                              int userId, int K, int N) {
            Map<Integer, Double> targetUser = data.get(userId); // 目标用户
            List<Map.Entry<Integer, Double>> similarUsers = new ArrayList<>(); // 与目标用户兴趣相似的用户
            for (Map.Entry<Integer, Map<Integer, Double>> entry: data.entrySet()) {
                int id = entry.getKey();
                if (id == userId)
                    continue;
                double sim = pearsonCorrelation(targetUser, entry.getValue(), data); // 计算皮尔逊相关系数
                if (sim > 0)
                    similarUsers.add(new AbstractMap.SimpleEntry<>(id, sim));
            }
            Collections.sort(similarUsers, (a, b) -> b.getValue().compareTo(a.getValue())); // 按相似度从高到低排序
            List<Integer> itemIds = new ArrayList<>();
            for (int i = 0; i < K && i < similarUsers.size(); i++) {
                Map.Entry<Integer, Double> entry = similarUsers.get(i);
                int userId2 = entry.getKey();
                Map<Integer, Double> user2 = data.get(userId2);
                for (int itemId: user2.keySet()) {
                    if (!targetUser.containsKey(itemId)) { // 如果目标用户没看过该帖子
                        itemIds.add(itemId);
                    }
                }
            }
            Map<Integer, Double> scores = new HashMap<>();
            for (int itemId: itemIds) {
                double score = 0;
                int count = 0;
                for (Map.Entry<Integer, Double> entry: similarUsers) {
                    int userId2 = entry.getKey();
                    Map<Integer, Double> user2 = data.get(userId2);
                    if (user2.containsKey(itemId)) { // 如果用户 2 看过该帖子
                        score += entry.getValue() * user2.get(itemId);
                        count++;
                        if (count == N)
                            break;
                    }
                }
                scores.put(itemId, score);
            }
            List<Integer> pickedItemIds = new ArrayList<>();
            scores.entrySet().stream().sorted((a, b) -> b.getValue().compareTo(a.getValue()))
                    .limit(N).forEach(entry -> pickedItemIds.add(entry.getKey())); // 按得分从高到低排序并选出前N个
            return pickedItemIds;
        }
    }
4. コンテンツ ベースの推奨アルゴリズム

コンテンツ ベースの推奨アルゴリズムは、別のタイプの推奨アルゴリズムです。推奨システム: 属性の類似性に基づいて項目を推奨する一般的な方法。ここでは、コンテンツベースの推奨アルゴリズムを使用して、適切な投稿をユーザーに推奨します。具体的な手順は次のとおりです。

対象ユーザーについては、フォローしているトピックや公開する投稿などを選択します。

    これらの内容をもとに、各投稿と対象ユーザーの興味関心との類似度を計算します。
  1. ターゲット ユーザーの興味に最も近い上位 N 個の投稿を選択します。
  2. スコアの高いものから低いものの順に並べ替え、スコアが最も高い上位 M 件の投稿を推奨結果として選択します。
  3. 以下は、コンテンツベースの推奨アルゴリズムの Java コード実装です:
  4. public class ContentBasedRecommendation {
    
        /**
         * 计算两个向量的余弦相似度
         * @param v1 向量1
         * @param v2 向量2
         * @return 余弦相似度
         */
        public double cosineSimilarity(double[] v1, double[] v2) {
            double dotProduct = 0;
            double norma = 0;
            double normb = 0;
            for (int i = 0; i < v1.length; i++) {
                dotProduct += v1[i] * v2[i];
                norma += Math.pow(v1[i], 2);
                normb += Math.pow(v2[i], 2);
            }
            if (norma == 0 || normb == 0)
                return 0;
            return dotProduct / (Math.sqrt(norma) * Math.sqrt(normb));
        }
    
        /**
         * 基于内容的推荐算法
         * @param data 数据集
         * @param userId 目标用户 ID
         * @param N 推荐的 N 个帖子
         * @return 推荐的帖子 ID 列表
         */
        public List<Integer> contentBasedRecommendation(Map<Integer, Map<Integer, Double>> data,
                                                         int userId, int N) {
            Map<Integer, Double> targetUser = data.get(userId); // 目标用户
            int[] pickedItems = new int[data.size()];
            double[][] itemFeatures = new double[pickedItems.length][24]; // 物品特征矩阵
            for (Map.Entry<Integer, Map<Integer, Double>> entry: data.entrySet()) {
                int itemId = entry.getKey();
                Map<Integer, Double> item = entry.getValue();
                double[] feature = new double[24];
                for (int i = 0; i < feature.length; i++) {
                    if (item.containsKey(i+1)) {
                        feature[i] = item.get(i+1);
                    } else {
                        feature[i] = 0;
                    }
                }
                itemFeatures[itemId-1] = feature; // 物品 ID 从 1 开始,需要减一
            }
            for (int itemId: targetUser.keySet()) {
                pickedItems[itemId-1] = 1; // 物品 ID 从 1 开始,需要减一
            }
            double[] similarities = new double[pickedItems.length];
            for (int i = 0; i < similarities.length; i++) {
                if (pickedItems[i] == 0) {
                    similarities[i] = cosineSimilarity(targetUser.values().stream().mapToDouble(Double::doubleValue).toArray(), itemFeatures[i]);
                }
            }
            List<Integer> itemIds = new ArrayList<>();
            while (itemIds.size() < N) {
                int maxIndex = -1;
                for (int i = 0; i < similarities.length; i++) {
                    if (pickedItems[i] == 0 && (maxIndex == -1 || similarities[i] > similarities[maxIndex])) {
                        maxIndex = i;
                    }
                }
                if (maxIndex == -1 || similarities[maxIndex] < 0) {
                    break; // 找不到更多相似的物品了
                }
                itemIds.add(maxIndex + 1); // 物品 ID 从 1 开始,需要加一
                pickedItems[maxIndex] = 1;
            }
            Map<Integer, Double> scores = new HashMap<>();
            for (int itemId: itemIds) {
                double[] features = itemFeatures[itemId-1]; // 物品 ID 从 1 开始,需要减一
                double score = cosineSimilarity(targetUser.values().stream().mapToDouble(Double::doubleValue).toArray(), features);
                scores.put(itemId, score);
            }
            List<Integer> pickedItemIds = new ArrayList<>();
            scores.entrySet().stream().sorted((a, b) -> b.getValue().compareTo(a.getValue()))
                    .limit(N).forEach(entry -> pickedItemIds.add(entry.getKey())); // 按得分从高到低排序并选出前N个
            return pickedItemIds;
        }
    }
5. 推奨アルゴリズムをアプリケーションに統合します

上記の作業を完了した後、 2 つの推奨アルゴリズム 実装したら、アプリケーションに統合できます。具体的な手順は次のとおりです。

データをロードし、データベースに保存します。 Hibernate などの ORM フレームワークを使用すると、データベースへのアクセス操作を簡素化できます。

    HTTP リクエストを受け入れ、JSON 形式でレスポンスを返す RESTful API を定義します。 Spring Framework を使用して RESTful API を構築およびデプロイできます。
  1. ユーザーベースの協調フィルタリング推奨アルゴリズムとコンテンツベースの推奨アルゴリズムを実装し、RESTful API に統合します。
  2. 次は、アプリケーションの Java コード実装です:
  3. @RestController
    @RequestMapping("/recommendation")
    public class RecommendationController {
    
        private CollaborativeFiltering collaborativeFiltering = new CollaborativeFiltering();
        private ContentBasedRecommendation contentBasedRecommendation = new ContentBasedRecommendation();
    
        @Autowired
        private UserService userService;
    
        @GetMapping("/userbased/{userId}")
        public List<Integer> userBasedRecommendation(@PathVariable Integer userId) {
            List<User> allUsers = userService.getAllUsers();
            Map<Integer, Map<Integer, Double>> data = new HashMap<>();
            for (User user: allUsers) {
                Map<Integer, Double> userVector = new HashMap<>();
                List<Topic> followedTopics = user.getFollowedTopics();
                for (Topic topic: followedTopics) {
                    userVector.put(topic.getId(), 1.0);
                }
                List<Post> posts = user.getPosts();
                for (Post post: posts) {
                    userVector.put(post.getId() + 1000, 1.0);
                }
                List<Comment> comments = user.getComments();
                for (Comment comment: comments) {
                    userVector.put(comment.getId() + 2000, 1.0);
                }
                List<Like> likes = user.getLikes();
                for (Like like: likes) {
                    userVector.put(like.getId() + 3000, 1.0);
                }
                data.put(user.getId(), userVector);
            }
            List<Integer> itemIds = collaborativeFiltering.userBasedCollaborativeFiltering(data, userId, 5, 10);
            return itemIds;
        }
    
        @GetMapping("/contentbased/{userId}")
        public List<Integer> contentBasedRecommendation(@PathVariable Integer userId) {
            List<User> allUsers = userService.getAllUsers();
            Map<Integer, Map<Integer, Double>> data = new HashMap<>();
            for (User user: allUsers) {
                Map<Integer, Double> userVector = new HashMap<>();
                List<Topic> followedTopics = user.getFollowedTopics();
                for (Topic topic: followedTopics) {
                    userVector.put(topic.getId(), 1.0);
                }
                List<Post> posts = user.getPosts();
                for (Post post: posts) {
                    userVector.put(post.getId() + 1000, 1.0);
                }
                List<Comment> comments = user.getComments();
                for (Comment comment: comments) {
                    userVector.put(comment.getId() + 2000, 1.0);
                }
                List<Like> likes = user.getLikes();
                for (Like like: likes) {
                    userVector.put(like.getId() + 3000, 1.0);
                }

以上がJava を使用してレコメンデーション システム ベースのソーシャル ネットワーク アプリケーションを作成する方法の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。