CoolFace
Apppublic

chintu67/karma_fraud_detector

sourceHugging Faceupdated 1y agoView on Hugging Face
0likes
generate_data.py338 linesDownload Raw Back to data
1import json
2import random
3import numpy as np
4from datetime import datetime, timedelta
5from typing import List, Dict, Any
6import os
7
8class RealisticUserGenerator:
9    def __init__(self, seed=42):
10        random.seed(seed)
11        np.random.seed(seed)
12
13        self.normal_comments = [
14            "Great discussion, thanks for posting!", "Insightful post, learned something new.",
15            "Well explained.", "Nice analysis!", "Really enjoyed reading this!", "Good find!",
16            "Appreciate the details!", "Thanks for the update.", "Helpful explanation.",
17            "Clear and concise.", "Agreed.", "Interesting!", "Makes sense.", "This is helpful.",
18            "Thanks!", "Nice!", "Fair point.", "True that."
19        ]
20
21        self.suspicious_comments = [
22            "Insane", "Fire post!", "Unreal", "Mind blown!", "Crazy good!", "This hits, up!",
23            "Epic, more pls!", "Legend post!", "Wild, upvote!", "Major W!", "Gold content!", "Hype this!",
24            "Wow", "Viral vibes!", "Straight fire!", "Facts, up!", "This slaps!", "Banger post!",
25            "Peak", "Truth, vote!", "King move!", "No cap, up!", "Lit content!", "Needed this, up!",
26            "Quick", "Short and sweet!", "Up this now!", "Keep it up!", "Nice, again!"
27        ]
28
29        self.spam_comments = [
30            "Upvote me now", "Check my page", "Pls upvote fast", "Boost this post",
31            "Click my link", "Vote me up", "Sub for sub", "Need karma fast",
32            "Karma farming", "Upvote exchange", "New here, need karma", "Follow back",
33            "Drop an upvote!", "Karma needed ASAP!", "Link in bio!", "Upvote for upvote!",
34            "Pls boost me!", "Check this out!", "Need votes now!", "Support my post!",
35            "Follow me quick!", "Karma trade?", "Vote this up!", "Join my page!",
36            "Upvote my stuff!", "Help me grow!", "Click here now!", "Karma plz!"
37        ]
38
39        # Add post content lists for each user type
40        self.normal_posts = [
41            "Exploring the latest tech trends in AI.",
42            "My experience with open source contributions.",
43            "Tips for effective remote work.",
44            "How to stay productive as a developer.",
45            "A review of the best programming languages in 2024.",
46            "Lessons learned from my first hackathon.",
47            "How to build a personal portfolio website.",
48            "Understanding the basics of machine learning.",
49            "Why code reviews matter in software teams.",
50            "Best resources for learning Python."
51        ]
52        self.suspicious_posts = [
53            "Unbelievable trick to get more followers!",
54            "Boost your karma instantly with this method.",
55            "You won't believe this hack for upvotes.",
56            "Get rich quick with this simple step.",
57            "Secret to viral posts revealed!",
58            "How I gained 1000 followers in a week!",
59            "This one trick will change your life!",
60            "Earn karma fast with this method!",
61            "Top secret upvote strategy!",
62            "Double your upvotes overnight!"
63        ]
64        self.fraudulent_posts = [
65            "Upvote me and I'll upvote you back!",
66            "Need karma fast, help me out!",
67            "Join my upvote group for instant karma.",
68            "Let's trade upvotes, comment below!",
69            "Karma exchange, DM me now!",
70            "Upvote for upvote, guaranteed!",
71            "Help me reach 1000 karma today!",
72            "Instant upvotes, just comment!",
73            "Karma farming, join now!",
74            "Upvote train, hop on!"
75        ]
76
77    def _add_noise(self, text):
78        if random.random() < 0.1:
79            text = text.lower() if random.random() < 0.5 else text.upper()
80        if random.random() < 0.05:
81            if len(text) > 2:
82                i = random.randint(1, len(text)-2)
83                text = text[:i] + text[i+1] + text[i] + text[i+2:]
84        if random.random() < 0.05:
85            if random.random() < 0.5:
86                text = text.replace(" ", "  ")
87            else:
88                text += text[-1]
89        if random.random() < 0.2:
90            text += random.choice(["!", "...", "๐Ÿ”ฅ", "๐Ÿ’ฏ", "๐Ÿ‘", "๐Ÿ˜Š", "๐Ÿš€", "๐Ÿ˜", "๐Ÿ‘€"])
91        return text
92
93    def _generate_timestamps(self, base_time, user_type, num_acts):
94        ts = []
95        now = base_time
96        for _ in range(num_acts):
97            gap = np.random.exponential(scale={
98                'normal': 72,
99                'suspicious': 24,
100                'fraudulent': 5
101            }[user_type])
102            now = now - timedelta(hours=gap)
103            ts.append(now)
104        return sorted(ts, reverse=True)
105
106    def generate_user(self, user_type, user_id):
107        base_time = datetime.now()
108        user = {
109            "user_id": user_id,
110            "account_age_days": 0,
111            "karma_log": [],
112            "label": user_type
113        }
114
115        if user_type == 'normal':
116            user["account_age_days"] = random.randint(15, 1000)
117        elif user_type == 'suspicious':
118            user["account_age_days"] = random.randint(3, 50)
119        else:
120            user["account_age_days"] = random.randint(1, 15)
121
122        num_posts = random.randint(1, 2)
123        num_comments = random.randint(2, 6)
124        num_upvotes = random.randint(3, 7)
125        total = num_posts + num_comments + num_upvotes
126        timestamps = self._generate_timestamps(base_time, user_type, total)
127
128        # --- Post Created ---
129        posts = []
130        for i in range(num_posts):
131            if user_type == 'normal':
132                post_content = self._add_noise(random.choice(self.normal_posts))
133            elif user_type == 'suspicious':
134                post_content = self._add_noise(random.choice(self.suspicious_posts))
135            else:
136                post_content = self._add_noise(random.choice(self.fraudulent_posts))
137            posts.append(post_content)
138            user["karma_log"].append({
139                "activity_id": f"act_{user_type[0]}_{user_id}_p{i}",
140                "type": "post_created",
141                "content": post_content,
142                "timestamp": timestamps[i].isoformat() + "Z"
143            })
144
145        # --- Comments ---
146        comment_pool = []
147        if user_type == 'normal':
148            comment_pool = self.normal_comments + (self.suspicious_comments[:5] if random.random() < 0.3 else [])
149        elif user_type == 'suspicious':
150            bot_upvote_ratio = np.random.uniform(0.3, 0.8)
151            comment_pool = self.suspicious_comments[:]
152            if random.random() < 0.4:
153                comment_pool += random.sample(self.normal_comments, 5)
154            if random.random() < 0.3:
155                comment_pool += random.sample(self.spam_comments, 3)
156            base_comment = random.choice(comment_pool)
157            comments = []
158            for _ in range(num_comments):
159                if random.random() < 0.3:
160                    comments.append(self._add_noise(base_comment))
161                else:
162                    comments.append(self._add_noise(random.choice(comment_pool)))
163        else:
164            comment_pool = self.spam_comments + (self.suspicious_comments[:3] if random.random() < 0.2 else [])
165            comments = [self._add_noise(random.choice(comment_pool)) for _ in range(num_comments)]
166            bot_upvote_ratio = np.random.uniform(0.8, 1.2)
167            burst_count = np.random.randint(1, 5)
168
169        if user_type != 'suspicious':
170            comments = [self._add_noise(random.choice(comment_pool)) for _ in range(num_comments)]
171
172        if user_type == 'normal' and random.random() < 0.1:
173            comments[0] = random.choice(self.spam_comments)
174        if user_type == 'fraudulent' and random.random() < 0.2:
175            comments[0] = random.choice(self.normal_comments)
176
177        for i, content in enumerate(comments):
178            user["karma_log"].append({
179                "activity_id": f"act_{user_type[0]}_{user_id}_c{i}",
180                "type": "comment",
181                "content": content,
182                "timestamp": timestamps[num_posts + i].isoformat() + "Z"
183            })
184
185        # --- Upvotes (Received & Sent) ---
186        for i in range(num_upvotes):
187            upvote_timestamp = timestamps[num_posts + num_comments + i].isoformat() + "Z"
188            if user_type == 'normal':
189                from_user_age = random.randint(30, 500)
190                from_user = f"usr_{random.randint(1000,9999)}"
191                # Upvote received
192                user["karma_log"].append({
193                    "activity_id": f"act_{user_type[0]}_{user_id}_u{i}",
194                    "type": "upvote_received",
195                    "from_user": from_user,
196                    "from_user_age_days": from_user_age,
197                    "timestamp": upvote_timestamp
198                })
199                # Upvote sent (to a random user)
200                sent_to_user = f"usr_{random.randint(1000,9999)}"
201                user["karma_log"].append({
202                    "activity_id": f"act_{user_type[0]}_{user_id}_us{i}",
203                    "type": "upvote_sent",
204                    "to_user": sent_to_user,
205                    "to_user_age_days": random.randint(10, 1000),
206                    "timestamp": upvote_timestamp
207                })
208            elif user_type == 'suspicious':
209                from_user_age = random.choices(
210                    [random.randint(2, 5), random.randint(30, 100)],
211                    weights=[0.6, 0.4],
212                    k=1
213                )[0]
214                from_user = f"usr_{random.randint(1000,9999)}"
215                # Upvote received
216                user["karma_log"].append({
217                    "activity_id": f"act_{user_type[0]}_{user_id}_u{i}",
218                    "type": "upvote_received",
219                    "from_user": from_user,
220                    "from_user_age_days": from_user_age,
221                    "timestamp": upvote_timestamp
222                })
223                # Upvote sent (to a random user)
224                sent_to_user = f"usr_{random.randint(1000,9999)}"
225                user["karma_log"].append({
226                    "activity_id": f"act_{user_type[0]}_{user_id}_us{i}",
227                    "type": "upvote_sent",
228                    "to_user": sent_to_user,
229                    "to_user_age_days": random.randint(2, 100),
230                    "timestamp": upvote_timestamp
231                })
232            else:  # fraudulent
233                # For fraudulent, mutual upvotes: upvote_received and upvote_sent to the same user, but with slightly different timestamps
234                mutual_user = f"usr_{random.randint(1000,9999)}"
235                mutual_user_age = random.randint(1, 10)
236                # Generate two close but not identical timestamps
237                base_upvote_time = timestamps[num_posts + num_comments + i]
238                offset_minutes = random.randint(1, 60)
239                if random.random() < 0.5:
240                    sent_time = base_upvote_time + timedelta(minutes=offset_minutes)
241                    received_time = base_upvote_time
242                else:
243                    sent_time = base_upvote_time
244                    received_time = base_upvote_time + timedelta(minutes=offset_minutes)
245                # Upvote received
246                user["karma_log"].append({
247                    "activity_id": f"act_{user_type[0]}_{user_id}_u{i}",
248                    "type": "upvote_received",
249                    "from_user": mutual_user,
250                    "from_user_age_days": mutual_user_age,
251                    "timestamp": received_time.isoformat() + "Z"
252                })
253                # Upvote sent (to the same user)
254                user["karma_log"].append({
255                    "activity_id": f"act_{user_type[0]}_{user_id}_us{i}",
256                    "type": "upvote_sent",
257                    "to_user": mutual_user,
258                    "to_user_age_days": mutual_user_age,
259                    "timestamp": sent_time.isoformat() + "Z"
260                })
261
262        return user
263
264    def generate_dataset(self, n_normals, n_suspicious, n_fraud, flip_ratio=0.05):
265        dataset = []
266        for i in range(n_normals):
267            dataset.append(self.generate_user("normal", f"normal_{i+1:04}"))
268        for i in range(n_suspicious):
269            dataset.append(self.generate_user("suspicious", f"suspicious_{i+1:04}"))
270        for i in range(n_fraud):
271            dataset.append(self.generate_user("fraudulent", f"fraudulent_{i+1:04}"))
272
273        total = len(dataset)
274        flip_count = int(total * flip_ratio)
275        flip_targets = random.sample(dataset, flip_count)
276        for user in flip_targets:
277            original = user["label"]
278            choices = ["normal", "suspicious", "fraudulent"]
279            choices.remove(original)
280            user["label"] = random.choice(choices)
281
282        random.shuffle(dataset)
283        return dataset
284
285def add_noise_to_label(label, noise_level=0.15):
286    if random.random() < noise_level:
287        choices = ['normal', 'suspicious', 'fraudulent']
288        choices.remove(label)
289        return random.choice(choices)
290    return label
291
292def generate_realistic_hard_dataset(n_normals, n_suspicious, n_fraud, flip_ratio=0.10, overlap_ratio=0.25):
293    generator = RealisticUserGenerator(seed=42)
294    dataset = []
295    for i in range(n_normals):
296        user = generator.generate_user('normal', f'normal_{i+1:04}')
297        user['account_age_days'] = random.randint(15, 1000)
298        if random.random() < overlap_ratio:
299            user['karma_log'][0]['content'] = random.choice(generator.spam_comments + generator.suspicious_comments)
300        user['label'] = add_noise_to_label(user['label'], noise_level=flip_ratio)
301        dataset.append(user)
302    for i in range(n_suspicious):
303        user = generator.generate_user('suspicious', f'suspicious_{i+1:04}')
304        if random.random() < 0.15:
305            user['account_age_days'] = random.randint(1, 15)
306        else:
307            user['account_age_days'] = random.randint(15, 1000)
308        if random.random() < overlap_ratio:
309            user['karma_log'][0]['content'] = random.choice(generator.normal_comments)
310        user['label'] = add_noise_to_label(user['label'], noise_level=flip_ratio)
311        dataset.append(user)
312    for i in range(n_fraud):
313        user = generator.generate_user('fraudulent', f'fraudulent_{i+1:04}')
314        if random.random() < 0.15:
315            user['account_age_days'] = random.randint(1, 15)
316        else:
317            user['account_age_days'] = random.randint(15, 1000)
318        if random.random() < overlap_ratio:
319            user['karma_log'][0]['content'] = random.choice(generator.normal_comments + generator.suspicious_comments)
320        user['label'] = add_noise_to_label(user['label'], noise_level=flip_ratio)
321        dataset.append(user)
322    random.shuffle(dataset)
323    return dataset
324
325def main():
326    os.makedirs("data", exist_ok=True)
327    print('Generating optimal training set...')
328    train_optimal = generate_realistic_hard_dataset(400, 240, 160, flip_ratio=0.10, overlap_ratio=0.25)
329    print('Generating optimal test set...')
330    test_optimal = generate_realistic_hard_dataset(100, 60, 40, flip_ratio=0.10, overlap_ratio=0.25)
331    with open('data/optimal_train.json', 'w') as f:
332        json.dump(train_optimal, f, indent=2)
333    with open('data/optimal_test.json', 'w') as f:
334        json.dump(test_optimal, f, indent=2)
335    print('โœ… Done! Optimal Training:', len(train_optimal), 'Test:', len(test_optimal))
336
337if __name__ == "__main__":
338    main()