前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Auto-Tinder-训练AI玩打火机刷卡游戏

Auto-Tinder-训练AI玩打火机刷卡游戏

作者头像
代码医生工作室
发布2019-10-31 13:26:26
1.5K0
发布2019-10-31 13:26:26
举报
文章被收录于专栏:相约机器人相约机器人

在本文档中,将解释创建自动绑定所需的以下步骤:

  • 分析tinder网页以找出tinder内部API调用的内容,在Postman中重构API调用并分析其内容
  • 在python中建立一个API包装器类别,使用Tinder API进行喜欢/不喜欢/比赛等。
  • 下载一堆附近人的图像
  • 编写简单的鼠标单击分类器来标记我们的图像
  • 开发一个使用tensorflow对象检测API的预处理器以仅裁剪图像中的人物
  • 训练Inceptionv3(一种深度卷积神经网络),以学习分类数据
  • 将分类器与tinder API包装器结合使用播放tinder

https://www.getpostman.com/

步骤0:动机和免责声明

Auto Tinder是一个纯粹出于娱乐和教育目的而创建的概念项目。绝不能滥用它来伤害任何人或向平台发送垃圾邮件。自动绑定脚本不应与您的绑定文件一起使用,因为它们肯定违反了绑定服务条款。

编写此软件的原因主要有两个:

  • 因为可以,创建它很有趣:)
  • 想弄清楚一个AI是否真的能够了解我的另一性,并成为我可靠的左右滑动伙伴。

步骤1:分析Tinder API

第一步是找出tinder应用程序如何与tender后端服务器进行通信。由于tinder提供其门户网站的网络版本,因此与访问tinder.com一样简单,它可以打开chrome devtools并快速查看网络协议。

上图中显示的内容是从请求发送到链接的请求,该请求是在tinder.com着陆页加载时发出的。显然,tinder具有某种内部API,正在使用它们在前端和后端之间进行通信。

https://api.gotinder.com/v2/recs/core

通过分析/ recs / core的内容,可以清楚地看到此API端点返回附近人员的用户个人资料列表。

该数据包括(在许多其他字段中)以下数据:

代码语言:javascript
复制
{
    "meta": {
        "status": 200
    },
    "data": {
        "results": [
            {
                "type": "user",
                "user": {
                 "_id": "4adfwe547s8df64df",
                    "bio": "19y.",
                    "birth_date": "1997-17-06T18:21:44.654Z",
                    "name": "Anna",
                    "photos": [
                        {
                            "id": "879sdfert-lskdföj-8asdf879-987sdflkj",
                            "crop_info": {
                                "user": {
                                    "width_pct": 1,
                                    "x_offset_pct": 0,
                                    "height_pct": 0.8,
                                    "y_offset_pct": 0.08975463
                                },
                                "algo": {
                                    "width_pct": 0.45674357,
                                    "x_offset_pct": 0.984341657,
                                    "height_pct": 0.234165403,
                                    "y_offset_pct": 0.78902343
                                },
                                "processed_by_bullseye": true,
                                "user_customized": false
                            },
                            "url": "https://images-ssl.gotinder.com/4adfwe547s8df64df/original_879sdfert-lskdföj-8asdf879-987sdflkj.jpeg",
                            "processedFiles": [
                                {
                                    "url": "https://images-ssl.gotinder.com/4adfwe547s8df64df/640x800_879sdfert-lskdföj-8asdf879-987sdflkj.jpg",
                                    "height": 800,
                                    "width": 640
                                },
                                {
                                    "url": "https://images-ssl.gotinder.com/4adfwe547s8df64df/320x400_879sdfert-lskdföj-8asdf879-987sdflkj.jpg",
                                    "height": 400,
                                    "width": 320
                                },
                                {
                                    "url": "https://images-ssl.gotinder.com/4adfwe547s8df64df/172x216_879sdfert-lskdföj-8asdf879-987sdflkj.jpg",
                                    "height": 216,
                                    "width": 172
                                },
                                {
                                    "url": "https://images-ssl.gotinder.com/4adfwe547s8df64df/84x106_879sdfert-lskdföj-8asdf879-987sdflkj.jpg",
                                    "height": 106,
                                    "width": 84
                                }
                            ],
                            "last_update_time": "2019-10-03T16:18:30.532Z",
                            "fileName": "879sdfert-lskdföj-8asdf879-987sdflkj.webp",
                            "extension": "jpg,webp",
                            "webp_qf": [
                                75
                            ]
                        }
                    ],
                    "gender": 1,
                    "jobs": [],
                    "schools": [],
                    "show_gender_on_profile": false
                },
                "facebook": {
                    "common_connections": [],
                    "connection_count": 0,
                    "common_interests": []
                },
                "spotify": {
                    "spotify_connected": false
                },
                "distance_mi": 1,
                "content_hash": "slkadjfiuwejsdfuzkejhrsdbfskdzufiuerwer",
                "s_number": 9876540657341,
                "teaser": {
                    "string": ""
                },
                "teasers": [],
                "snap": {
                    "snaps": []
                }
            }
        ]
    }
}

这里有几件事非常有趣(请注意,更改了所有数据以不侵犯此人的隐私):

  • 所有图像均可公开访问。如果复制图像URL并在私人窗口中打开它,它仍然会立即加载-这意味着tinder将所有用户图像公开上传到Internet,任何人都可以自由查看。
  • 通过API可访问的原始照片具有极高的分辨率。如果将照片上传到tinder,将按比例缩小以适合应用程序内使用,但会将原始版本公开存储在其服务器上,任何人都可以访问。
  • 即使您选择“ show_gender_on_profile”,每个人仍然可以通过API查看性别(“性别”:1,其中1 =女人,0 =男人)
  • 如果连续向tinder API发送多个请求,则始终会得到不同的结果(例如,不同的配置文件)。因此,可以反复地将此端点称为“农场”一堆图片,以后可以用来训练神经网络。

通过分析内容标头,我们可以快速找到私有API密钥:X-Auth-Token。

通过复制此令牌并转到Postman,可以验证确实可以仅使用正确的URL和auth令牌与tinder API自由通信。

通过一点点单击tinders webapp,很快发现了所有相关的API端点:

第2步:在Python中构建API包装器

因此进入代码。为了方便起见,将使用python Requests库与API通信并在其周围编写一个API包装器类。

https://requests.kennethreitz.org/en/master/

同样,编写了一个小的Person类,该类从Tinder接收代表一个Person的API响应,并提供了一些与Tinder API的基本接口。

从Person类开始。它应接收API数据,tinder-api对象,并将所有相关数据保存到实例变量中。它还将提供一些基本功能,例如“喜欢”或“不喜欢”,这些请求向tinder-api发出了请求,这使能够方便地使用“ some_person.like()”来喜欢发现有趣的配置文件。

代码语言:javascript
复制
import datetime
from geopy.geocoders import Nominatim
 
TINDER_URL = "https://api.gotinder.com"
geolocator = Nominatim(user_agent="auto-tinder")
PROF_FILE = "./images/unclassified/profiles.txt"
 
class Person(object):
 
    def __init__(self, data, api):
        self._api = api
 
        self.id = data["_id"]
        self.name = data.get("name", "Unknown")
 
        self.bio = data.get("bio", "")
        self.distance = data.get("distance_mi", 0) / 1.60934
 
        self.birth_date = datetime.datetime.strptime(data["birth_date"], '%Y-%m-%dT%H:%M:%S.%fZ') if data.get(
            "birth_date", False) else None
        self.gender = ["Male", "Female", "Unknown"][data.get("gender", 2)]
 
        self.images = list(map(lambda photo: photo["url"], data.get("photos", [])))
 
        self.jobs = list(
            map(lambda job: {"title": job.get("title", {}).get("name"), "company": job.get("company", {}).get("name")}, data.get("jobs", [])))
        self.schools = list(map(lambda school: school["name"], data.get("schools", [])))
 
        if data.get("pos", False):
            self.location = geolocator.reverse(f'{data["pos"]["lat"]}, {data["pos"]["lon"]}')
 
 
    def __repr__(self):
        return f"{self.id}  -  {self.name} ({self.birth_date.strftime('%d.%m.%Y')})"
 
 
    def like(self):
        return self._api.like(self.id)
 
    def dislike(self):
        return self._api.dislike(self.id)

API包装器不过是使用类调用tinder API的理想方式:

代码语言:javascript
复制
import requests
 
TINDER_URL = "https://api.gotinder.com"
 
class tinderAPI():
 
    def __init__(self, token):
        self._token = token
 
    def profile(self):
        data = requests.get(TINDER_URL + "/v2/profile?include=account%2Cuser", headers={"X-Auth-Token": self._token}).json()
        return Profile(data["data"], self)
 
    def matches(self, limit=10):
        data = requests.get(TINDER_URL + f"/v2/matches?count={limit}", headers={"X-Auth-Token": self._token}).json()
        return list(map(lambda match: Person(match["person"], self), data["data"]["matches"]))
 
    def like(self, user_id):
        data = requests.get(TINDER_URL + f"/like/{user_id}", headers={"X-Auth-Token": self._token}).json()
        return {
            "is_match": data["match"],
            "liked_remaining": data["likes_remaining"]
        }
 
    def dislike(self, user_id):
        requests.get(TINDER_URL + f"/pass/{user_id}", headers={"X-Auth-Token": self._token}).json()
        return True
 
    def nearby_persons(self):
        data = requests.get(TINDER_URL + "/v2/recs/core", headers={"X-Auth-Token": self._token}).json()
        return list(map(lambda user: Person(user["user"], self), data["data"]["results"]))

现在,可以使用API查找附近的人,并查看个人资料,甚至可以查看所有人。将API令牌替换为之前在chrome开发者控制台中找到的X-Auth-Token。

代码语言:javascript
复制
if __name__ == "__main__":
    token = "YOUR-API-TOKEN"
    api = tinderAPI(token)
 
    while True:
        persons = api.nearby_persons()
        for person in persons:
            print(person)
            # person.like()

第3步:下载附近人的图像

接下来,要自动下载附近的人的一些图像,以用于训练AI。“有些”是指1500-2500张图像。

首先,通过一个允许下载图像的函数来扩展Person类。

代码语言:javascript
复制
# At the top of auto_tinder.py
PROF_FILE = "./images/unclassified/profiles.txt"
 
# inside the Person-class
    def download_images(self, folder=".", sleep_max_for=0):
        with open(PROF_FILE, "r") as f:
            lines = f.readlines()
            if self.id in lines:
                return
        with open(PROF_FILE, "a") as f:
            f.write(self.id+"\r\n")
        index = -1
        for image_url in self.images:
            index += 1
            req = requests.get(image_url, stream=True)
            if req.status_code == 200:
                with open(f"{folder}/{self.id}_{self.name}_{index}.jpeg", "wb") as f:
                    f.write(req.content)
            sleep(random()*sleep_max_for)

请注意,在这里和那里添加了一些随机睡眠,这是因为如果向垃圾邮件CDN发送垃圾邮件并在短短几秒钟内下载许多图片,可能会被阻止。

将所有人员档案ID写入名为“ profiles.txt”的文件中。通过首先扫描文档中是否已存在某个特定人员,可以跳过已经遇到的人员,并确保不会对人员进行多次分类(将在后面看到为什么会有这种风险)。

现在,可以遍历附近的人,并将图像下载到“未分类”文件夹中。

代码语言:javascript
复制
if __name__ == "__main__":
    token = "YOUR-API-TOKEN"
    api = tinderAPI(token)
 
    while True:
        persons = api.nearby_persons()
        for person in persons:
            person.download_images(folder="./images/unclassified", sleep_max_for=random()*3)
            sleep(random()*10)
        sleep(random()*10)

现在,可以简单地启动此脚本,并使其运行几个小时,以获取附近人员的一些Hundret个人资料图片。如果是tinder PRO用户,请立即更新位置,然后结识新朋友。

步骤4:手动分类图像

现在有很多图像可以使用,构建一个非常简单且丑陋的分类器。

它将仅循环遍历“未分类”文件夹中的所有图像,并在GUI窗口中打开该图像。通过右键单击某个人,可以将该人标记为“不喜欢”,而单击鼠标左键将该人标记为“喜欢”。这将在文件名后上表示:4tz3kjldfj3482.jpg将被更名为1_4tz3kjldfj3482.jpg如果纪念像为“像”,或0_4tz3kjldfj3482.jpg否则。标签like / dislike在文件名的开头编码为1/0。

使用tkinter快速编写此GUI:

代码语言:javascript
复制
from os import listdir, rename
from os.path import isfile, join
import tkinter as tk
from PIL import ImageTk, Image
 
IMAGE_FOLDER = "./images/unclassified"
 
images = [f for f in listdir(IMAGE_FOLDER) if isfile(join(IMAGE_FOLDER, f))]
unclassified_images = filter(lambda image: not (image.startswith("0_") or image.startswith("1_")), images)
current = None
 
def next_img():
    global current, unclassified_images
    try:
        current = next(unclassified_images)
    except StopIteration:
        root.quit()
    print(current)
    pil_img = Image.open(IMAGE_FOLDER+"/"+current)
    width, height = pil_img.size
    max_height = 1000
    if height > max_height:
        resize_factor = max_height / height
        pil_img = pil_img.resize((int(width*resize_factor), int(height*resize_factor)), resample=Image.LANCZOS)
    img_tk = ImageTk.PhotoImage(pil_img)
    img_label.img = img_tk
    img_label.config(image=img_label.img)
 
def positive(arg):
    global current
    rename(IMAGE_FOLDER+"/"+current, IMAGE_FOLDER+"/1_"+current)
    next_img()
 
def negative(arg):
    global current
    rename(IMAGE_FOLDER + "/" + current, IMAGE_FOLDER + "/0_" + current)
    next_img()
 
 
if __name__ == "__main__":
 
    root = tk.Tk()
 
    img_label = tk.Label(root)
    img_label.pack()
    img_label.bind("<Button-1>", positive)
    img_label.bind("<Button-3>", negative)
 
    btn = tk.Button(root, text='Next image', command=next_img)
 
    next_img() # load first image
 
root.mainloop()

将所有未分类的图像加载到“ unclassified_images”列表中,打开一个tkinter窗口,通过调用next_img()将第一张图像打包到其中,并调整图像的大小以适合屏幕。然后,单击鼠标左键和鼠标右键两次,并调用正/负函数,该函数会根据其标签重命名图像并显示下一张图像。

丑陋但有效。

第5步:开发预处理程序以仅裁剪图像中的人物

下一步,需要将图像数据转换为允许分类的格式。给定数据集,必须考虑一些困难。

  • 数据集大小:数据集相对较小。考虑到图像的复杂性,处理+ -2000张图像,这被认为是非常少量的数据(高分辨率的RGB图像)
  • 数据差异:这些图片有时包含来自背后的人物,有时仅包含面孔,有时甚至根本没有人物。
  • 数据噪音:大多数图片不仅包含人物本身,而且通常包含周围的环境,这可能分散四个AI的注意力。

通过以下方式应对这些挑战:

  • 将图像转换为灰度,以将AI必须学习的信息量减少三倍(RGB到G)
  • 仅切出图像中实际包含该人的部分,仅此而已

第一部分就像使用“枕头”打开图像并将其转换为灰度图一样容易。对于第二部分,将 Tensorflow对象检测API与mobilenet网络体系结构一起使用,在可可数据集上进行了预训练,该数据集还包含“人”的标签。

https://github.com/tensorflow/models/tree/master/research/object_detection

人检测脚本包含四个部分:

第1部分:打开预训练的mobilenet可可数据集作为Tensorflow图

可以在Github存储库中找到tensorflow mobilenet可可图的.bp文件。将其作为Tensorflow图打开:

代码语言:javascript
复制
import tensorflow as tf
 
def open_graph():
    detection_graph = tf.Graph()
    with detection_graph.as_default():
        od_graph_def = tf.GraphDef()
        with tf.gfile.GFile('ssd_mobilenet_v1_coco_2017_11_17/frozen_inference_graph.pb', 'rb') as fid:
            serialized_graph = fid.read()
            od_graph_def.ParseFromString(serialized_graph)
            tf.import_graph_def(od_graph_def, name='')
return detection_graph

第2部分:以numpy数组的形式加载图像

使用枕头进行图像处理。由于tensorflow需要原始的numpy数组来处理数据,因此编写一个小函数将Pillow图像转换为numpy数组:

代码语言:javascript
复制
import numpy as np
 
def load_image_into_numpy_array(image):
    (im_width, im_height) = image.size
    return np.array(image.getdata()).reshape(
        (im_height, im_width, 3)).astype(np.uint8)

第3部分:调用对象检测API

下一个函数获取图像和张量流图,使用它运行一个张量流会话,并返回有关检测到的类(对象类型),边界框和得分(确定正确检测到对象的确定性)的所有信息。

代码语言:javascript
复制
import numpy as np
from object_detection.utils import ops as utils_ops
import tensorflow as tf
 
def run_inference_for_single_image(image, sess):
    ops = tf.get_default_graph().get_operations()
    all_tensor_names = {output.name for op in ops for output in op.outputs}
    tensor_dict = {}
    for key in [
        'num_detections', 'detection_boxes', 'detection_scores',
        'detection_classes', 'detection_masks'
    ]:
        tensor_name = key + ':0'
        if tensor_name in all_tensor_names:
            tensor_dict[key] = tf.get_default_graph().get_tensor_by_name(
                tensor_name)
    if 'detection_masks' in tensor_dict:
        # The following processing is only for single image
        detection_boxes = tf.squeeze(tensor_dict['detection_boxes'], [0])
        detection_masks = tf.squeeze(tensor_dict['detection_masks'], [0])
        # Reframe is required to translate mask from box coordinates to image coordinates and fit the image size.
        real_num_detection = tf.cast(tensor_dict['num_detections'][0], tf.int32)
        detection_boxes = tf.slice(detection_boxes, [0, 0], [real_num_detection, -1])
        detection_masks = tf.slice(detection_masks, [0, 0, 0], [real_num_detection, -1, -1])
        detection_masks_reframed = utils_ops.reframe_box_masks_to_image_masks(
            detection_masks, detection_boxes, image.shape[1], image.shape[2])
        detection_masks_reframed = tf.cast(
            tf.greater(detection_masks_reframed, 0.5), tf.uint8)
        # Follow the convention by adding back the batch dimension
        tensor_dict['detection_masks'] = tf.expand_dims(
            detection_masks_reframed, 0)
    image_tensor = tf.get_default_graph().get_tensor_by_name('image_tensor:0')
 
    # Run inference
    output_dict = sess.run(tensor_dict,
                           feed_dict={image_tensor: image})
 
    # all outputs are float32 numpy arrays, so convert types as appropriate
    output_dict['num_detections'] = int(output_dict['num_detections'][0])
    output_dict['detection_classes'] = output_dict[
        'detection_classes'][0].astype(np.int64)
    output_dict['detection_boxes'] = output_dict['detection_boxes'][0]
    output_dict['detection_scores'] = output_dict['detection_scores'][0]
    if 'detection_masks' in output_dict:
        output_dict['detection_masks'] = output_dict['detection_masks'][0]
return output_dict 

第4部分:将所有内容组合在一起以找到人

最后一步是编写一个获取图像路径的函数,使用Pillow将其打开,调用对象检测api接口,并根据检测到的人的边界框裁剪图像。

代码语言:javascript
复制
import numpy as np
from PIL import Image
 
PERSON_CLASS = 1
SCORE_THRESHOLD = 0.5
 
def get_person(image_path, sess):
    img = Image.open(image_path)
    image_np = load_image_into_numpy_array(img)
    image_np_expanded = np.expand_dims(image_np, axis=0)
    output_dict = run_inference_for_single_image(image_np_expanded, sess)
 
    persons_coordinates = []
    for i in range(len(output_dict["detection_boxes"])):
        score = output_dict["detection_scores"][i]
        classtype = output_dict["detection_classes"][i]
        if score > SCORE_THRESHOLD and classtype == PERSON_CLASS:
            persons_coordinates.append(output_dict["detection_boxes"][i])
 
    w, h = img.size
    for person_coordinate in persons_coordinates:
        cropped_img = img.crop((
            int(w * person_coordinate[1]),
            int(h * person_coordinate[0]),
            int(w * person_coordinate[3]),
            int(h * person_coordinate[2]),
        ))
        return cropped_img
return None

第5部分:将所有图像移动到分类文件夹中

最后一步,编写一个脚本来循环遍历“未分类”文件夹中的所有图像,并使用先前开发的预处理步骤检查它们是否在名称中具有编码标签,从而将图像复制到“已分类”文件夹中的图像中:

代码语言:javascript
复制
import os
import person_detector
import tensorflow as tf
 
IMAGE_FOLDER = "./images/unclassified"
POS_FOLDER = "./images/classified/positive"
NEG_FOLDER = "./images/classified/negative"
 
 
if __name__ == "__main__":
    detection_graph = person_detector.open_graph()
 
    images = [f for f in os.listdir(IMAGE_FOLDER) if os.path.isfile(os.path.join(IMAGE_FOLDER, f))]
    positive_images = filter(lambda image: (image.startswith("1_")), images)
    negative_images = filter(lambda image: (image.startswith("0_")), images)
 
    with detection_graph.as_default():
        with tf.Session() as sess:
 
            for pos in positive_images:
                old_filename = IMAGE_FOLDER + "/" + pos
                new_filename = POS_FOLDER + "/" + pos[:-5] + ".jpg"
                if not os.path.isfile(new_filename):
                    img = person_detector.get_person(old_filename, sess)
                    if not img:
                        continue
                    img = img.convert('L')
                    img.save(new_filename, "jpeg")
 
            for neg in negative_images:
                old_filename = IMAGE_FOLDER + "/" + neg
                new_filename = NEG_FOLDER + "/" + neg[:-5] + ".jpg"
                if not os.path.isfile(new_filename):
                    img = person_detector.get_person(old_filename, sess)
                    if not img:
                        continue
                    img = img.convert('L')
                    img.save(new_filename, "jpeg")

每当运行此脚本时,所有标记的图像都将被处理并移入“分类”目录中的相应子文件夹中。

步骤6:重新训练inceptionv3并编写分类器

对于重新训练部分,将仅将tensorflows retrain.py 脚本与inceptionv3模型一起使用。

https://github.com/tensorflow/hub/blob/master/examples/image_retraining/retrain.py

使用以下参数在项目根目录中调用脚本:

代码语言:javascript
复制
python retrain.py --bottleneck_dir=tf/training_data/bottlenecks --model_dir=tf/training_data/inception --summaries_dir=tf/training_data/summaries/basic --output_graph=tf/training_output/retrained_graph.pb --output_labels=tf/training_output/retrained_labels.txt --image_dir=./images/classified --how_many_training_steps=50000 --testing_percentage=20 --learning_rate=0.001

在GTX 1080 ti上,学习大约需要15分钟,对于标记的数据集,最终精度约为80%,但这在很大程度上取决于输入数据和标记的质量。

训练过程的结果是“ tf / training_output / retrained_graph.pb”文件中的重新训练的inceptionV3模型。现在必须编写一个分类器类,该类可以有效地使用张量流图中的新权重进行分类预测。

写一个Classifier-Class,它以会话形式打开图形,并提供带有图像文件的“ classify”方法,该图像文件将返回具有与标签“ positive”和“ negative”相匹配的确定性值的dict。

该类将图的路径以及标签文件的路径作为输入,它们都位于“ tf / training_output /”文件夹中。开发了用于将图像文件转换为张量的辅助函数,可以将其馈入到图形中,还提供了用于加载图形和标签的辅助函数,以及一个重要的小函数,用于在完成使用后关闭图形。

代码语言:javascript
复制
import numpy as np
import tensorflow as tf
 
class Classifier():
    def __init__(self, graph, labels):
 
        self._graph = self.load_graph(graph)
        self._labels = self.load_labels(labels)
 
        self._input_operation = self._graph.get_operation_by_name("import/Placeholder")
        self._output_operation = self._graph.get_operation_by_name("import/final_result")
 
        self._session = tf.Session(graph=self._graph)
 
    def classify(self, file_name):
        t = self.read_tensor_from_image_file(file_name)
 
        # Open up a new tensorflow session and run it on the input
        results = self._session.run(self._output_operation.outputs[0], {self._input_operation.outputs[0]: t})
        results = np.squeeze(results)
 
        # Sort the output predictions by prediction accuracy
        top_k = results.argsort()[-5:][::-1]
 
        result = {}
        for i in top_k:
            result[self._labels[i]] = results[i]
 
        # Return sorted result tuples
        return result
 
    def close(self):
        self._session.close()
 
 
    @staticmethod
    def load_graph(model_file):
        graph = tf.Graph()
        graph_def = tf.GraphDef()
        with open(model_file, "rb") as f:
            graph_def.ParseFromString(f.read())
        with graph.as_default():
            tf.import_graph_def(graph_def)
        return graph
 
    @staticmethod
    def load_labels(label_file):
        label = []
        proto_as_ascii_lines = tf.gfile.GFile(label_file).readlines()
        for l in proto_as_ascii_lines:
            label.append(l.rstrip())
        return label
 
    @staticmethod
    def read_tensor_from_image_file(file_name,
                                    input_height=299,
                                    input_width=299,
                                    input_mean=0,
                                    input_std=255):
        input_name = "file_reader"
        file_reader = tf.read_file(file_name, input_name)
        image_reader = tf.image.decode_jpeg(
            file_reader, channels=3, name="jpeg_reader")
        float_caster = tf.cast(image_reader, tf.float32)
        dims_expander = tf.expand_dims(float_caster, 0)
        resized = tf.image.resize_bilinear(dims_expander, [input_height, input_width])
        normalized = tf.divide(tf.subtract(resized, [input_mean]), [input_std])
        sess = tf.Session()
        result = sess.run(normalized)
        return result

第7步:使用所有这些内容自动播放Tinder

现在已经有了分类器,从前面扩展“ Person”类,并使用“ predict_likeliness”函数对其进行扩展,该函数使用分类器实例来验证是否应喜欢给定的人。

代码语言:javascript
复制
# In the Person class
 
    def predict_likeliness(self, classifier, sess):
        ratings = []
        for image in self.images:
            req = requests.get(image, stream=True)
            tmp_filename = f"./images/tmp/run.jpg"
            if req.status_code == 200:
                with open(tmp_filename, "wb") as f:
                    f.write(req.content)
            img = person_detector.get_person(tmp_filename, sess)
            if img:
                img = img.convert('L')
                img.save(tmp_filename, "jpeg")
                certainty = classifier.classify(tmp_filename)
                pos = certainty["positive"]
                ratings.append(pos)
        ratings.sort(reverse=True)
        ratings = ratings[:5]
        if len(ratings) == 0:
            return 0.001
        return ratings[0]*0.6 + sum(ratings[1:])/len(ratings[1:])*0.4

现在,必须将所有拼图组合在一起。

首先,使用api令牌初始化tinder API。然后使用重新训练的图和标签将分类张量流图打开为张量流会话。然后获取附近的人员并进行可能性预测。

作为一个小小的奖励,如果Tinder上的人和我上同一所大学,添加了1.2的似然倍数,这样就更有可能与本地学生匹配。

对于所有预测的可能性得分为0.8的人,称其为“喜欢”,而其他所有人则为“不喜欢”。

将脚本开发为可以在脚本启动后的两个小时内自动播放。

代码语言:javascript
复制
from likeliness_classifier import Classifier
import person_detector
import tensorflow as tf
from time import time
 
if __name__ == "__main__":
    token = "YOUR-API-TOKEN"
    api = tinderAPI(token)
 
    detection_graph = person_detector.open_graph()
    with detection_graph.as_default():
        with tf.Session() as sess:
 
            classifier = Classifier(graph="./tf/training_output/retrained_graph.pb",
                                    labels="./tf/training_output/retrained_labels.txt")
 
            end_time = time() + 60*60*2
            while time() < end_time:
                try:
                    persons = api.nearby_persons()
                    pos_schools = ["Universität Zürich", "University of Zurich", "UZH"]
 
                    for person in persons:
                        score = person.predict_likeliness(classifier, sess)
 
                        for school in pos_schools:
                            if school in person.schools:
                                print()
                                score *= 1.2
 
                        print("-------------------------")
                        print("ID: ", person.id)
                        print("Name: ", person.name)
                        print("Schools: ", person.schools)
                        print("Images: ", person.images)
                        print(score)
 
                        if score > 0.8:
                            res = person.like()
                            print("LIKE")
                        else:
                            res = person.dislike()
                            print("DISLIKE")
                except Exception:
                    pass
 
classifier.close()

现在可以让脚本运行任意长的时间,并在不拖累拇指的情况下玩弄Tinder!

如果有任何疑问或发现错误,请随时为Github存储库做出贡献。

https://github.com/joelbarmettlerUZH/auto-tinder

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2019-10-29,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 相约机器人 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
内容分发网络 CDN
内容分发网络(Content Delivery Network,CDN)通过将站点内容发布至遍布全球的海量加速节点,使其用户可就近获取所需内容,避免因网络拥堵、跨运营商、跨地域、跨境等因素带来的网络不稳定、访问延迟高等问题,有效提升下载速度、降低响应时间,提供流畅的用户体验。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档