分类目录归档:Python 数据分析

Python 一键生成漂亮的生日快乐词云!

前段时间写了几篇关于生成词云的文章,其中包括:

Python 情人节超强技能 导出微信聊天记录生成词云

Python 绘制悼念的词云蜡烛

等等,但是这几篇文章的转化对象都必须是多词汇组成的,也就是说他们生成词云的条件是词组必须够多,只有一两个词的话无法生成完整词云。

最近遇到许多朋友有特殊的需求,他们只想把 【名字】和【生日快乐】两个词组在一起,祝他人生日快乐,不想弄太复杂的东西,基于前面两篇文章是无法做到的。今天我们就来说说如何用这么少的词汇生成漂亮的词云。

1.准备

开始之前,你要确保Python和pip已经成功安装在电脑上噢,如果没有,请访问这篇文章:超详细Python安装指南 进行安装。

Windows环境下打开Cmd(开始—运行—CMD),苹果系统环境下请打开Terminal(command+空格输入Terminal),准备开始输入命令安装依赖。

当然,我更推荐大家用VSCode编辑器,把本文代码Copy下来,在编辑器下方的终端装依赖模块,多舒服的一件事啊:Python 编程的最好搭档—VSCode 详细指南

输入以下命令安装我们所需要的依赖模块:

pip install wordcloud==1.5.0
pip install scipy==1.1.0
pip install multidict==4.5.2
pip install matplotlib==2.2.4
pip install fire==0.2.1
pip install numpy==1.16.4

看到 Successfully installed xxx 则说明安装成功。或公众号后台回复生日快乐可获得本文全部代码,然后进入文件夹,输入一行命令安装所有依赖:

pip install -r requirements.txt

如果你不想折腾代码,安装完依赖后,输入以下命令就可以生成你的词云:

python birthday.py 图片位置 对象姓名 

如:

python birthday.py example.png 宝典哥

2.编写代码

首先是引入词云对象,并初始化【生日快乐】和对方姓名:

    words = multidict.MultiDict()
    # 生日快乐和姓名的权重必须先初始化两个最大权重的
    words.add('生日快乐', 10)
    words.add(name, 12) 

细心的读者可能发现了,我们在这里用了MultiDict,这主要是因为wordcloud只允许接受【字典】数据结构,而Python内置的字典不允许重复值,所以我们只能引入multidict模块。

然后是插入新的生日快乐词云和对方姓名:

    # 随意插入新的词语
    for i in range(1000):
        words.add('生日', numpy.random.randint(1, 5))
        words.add('快乐', numpy.random.randint(1, 5))
        words.add(name, numpy.random.randint(1, 5)) 

然后我们需要对图片进行一些处理,现在网络上的图片很多都包含一些杂色,因此需要把这些杂色去掉:

def transform_format(val):
    # 用于去除杂色
    if val[0] > 245 and val[1] > 245 and val[2] > 245:
        val[0] = val[1] = val[2] = 255
        return val
    else:
        return val 

然后引入图片,去除杂色:

    # 设定图片
    bimg = imread(file)
    for color in range(len(bimg)):
        bimg[color] = list(map(transform_format, bimg[color]))

    wordcloud = WordCloud(
        background_color='white', mask=bimg,
        font_path='simhei.ttf'
    ).generate_from_frequencies(words) 

生成词云并渲染:

    # 生成词云
    bimgColors = ImageColorGenerator(bimg)

    # 渲染词云
    plt.axis("off")
    plt.imshow(wordcloud.recolor(color_func=bimgColors))
    plt.savefig(name+'.png')
    plt.show() 

完整代码如下:

# coding:utf-8
# Python 实用宝典
# 2020/03/23
import numpy
import multidict
import matplotlib.pyplot as plt
from scipy.misc import imread
from wordcloud import WordCloud, ImageColorGenerator

def transform_format(val):
    # 用于去除杂色
    if val[0] > 245 and val[1] > 245 and val[2] > 245:
        val[0] = val[1] = val[2] = 255
        return val
    else:
        return val

def gen_happy_birthday_cloud(file, name):
    words = multidict.MultiDict()
    # 生日快乐和姓名的权重必须先初始化两个最大权重的
    words.add('生日快乐', 10)
    words.add(name, 12)

    # 随意插入新的词语
    for i in range(1000):
        words.add('生日', numpy.random.randint(1, 5))
        words.add('快乐', numpy.random.randint(1, 5))
        words.add(name, numpy.random.randint(1, 5))

    # 设定图片
    bimg = imread(file)
    for color in range(len(bimg)):
        bimg[color] = list(map(transform_format, bimg[color]))

    wordcloud = WordCloud(
        background_color='white', mask=bimg,
        font_path='simhei.ttf'
    ).generate_from_frequencies(words)

    # 生成词云
    bimgColors = ImageColorGenerator(bimg)

    # 渲染词云
    plt.axis("off")
    plt.imshow(wordcloud.recolor(color_func=bimgColors))
    plt.savefig(name+'.png')
    plt.show()

# gen_happy_birthday_cloud('p2.png', '宝典哥')

3.整合一句运行

接下来,我们使用上次提到的 一行命令实现功能 将这个功能打包成输入命令就能运行的程序,比如:

python birthday.py 图片 宝典哥

在完整代码最后面加一行语句就行了:

import fire
fire.Fire(gen_happy_birthday_cloud) 

当然,别忘了还要import fire模块。最后实验一下:

python birthday.py example.png 宝典哥

我们的文章到此就结束啦,如果你喜欢我们今天的Python 教程,请持续关注我们,如果对你有帮助,麻烦在下面点一个赞/在看哦有任何问题都可以在下方留言区留言,我们都会耐心解答的!


​Python实用宝典 (pythondict.com)
不只是一个宝典
欢迎关注公众号:Python实用宝典

Python 计算 瑞幸和星巴克 谁的门店最多

如果不借助他人的数据,你能自己算出瑞幸咖啡和星巴克咖啡其各自的门店数量吗?

让你自己算出一个精确的值,你会使用什么方法进行计算一线城市门店数量?

难度高一点点,你怎么样才能知道二线城市的门店总数,甚至是全国的门店数量?

用我们今天的方法,你可以知道,瑞幸咖啡在一线城市的数量是:1634间,而星巴克则为:1587间

往下看答案之前,你可以想想有几种方法可以实现我们的目的。

1.准备

开始之前,你要确保Python和pip已经成功安装在电脑上噢,如果没有,请访问这篇文章:超详细Python安装指南 进行安装。

Windows环境下打开Cmd(开始—运行—CMD),苹果系统环境下请打开Terminal(command+空格输入Terminal),准备开始输入命令安装依赖。

当然,我更推荐大家用VSCode编辑器,把本文代码Copy下来,在编辑器下方的终端装依赖模块,多舒服的一件事啊:Python 编程的最好搭档—VSCode 详细指南

输入以下命令安装我们所需要的依赖模块:

pip install requests

看到 Successfully installed xxx 则说明安装成功。你可以在Python实用宝典公众号后台回复:咖啡门店数 获得本文完整数据和代码。

2.获取门店数

怎么样,文章开头提出的问题你想到答案了吗?

其实很简单,那就是调用地图的接口进行门店搜索。 通过这个方法,我们不仅可以算出门店的数量,还能得到每个门店的对应位置,并且可以用来做后续的数据分析:

所以现在问题就转化为找到有提供搜索接口的地图供应商,而且这个接口得是免费的,因此我找了腾讯地图的接口:

https://lbs.qq.com/

你只需要上去注册账号,申请Key即可调用相关的接口,申请完了记得开webserviceAPI,选择签名校验的形式调用接口:

2.1 初始化

为了使用API,我们得先初始化请求链接及其所需要的参数:

class LocationSearch(object):

    def __init__(self, keyword: str):
        self.keyword = keyword
        self.key = '你的Key'
        self.sk = '你的校验sk'
        self.url = (
            'https://apis.map.qq.com/ws/place/v1/search?'
            'boundary=region({},0)&key={}&keyword={}'
            '&page_index={}&page_size=20'
        )

Key是在你申请API权限的时候就会分配给你的,而sk是在你选择 签名校验 的形式调用接口时分配给你的。

那么我们如何用这两个数据请求接口呢?请看下面这个函数:

def request_data(self, location: str, page: int):
    """
    请求接口数据
    Arguments:
        location {str} -- 地点
        page {int} -- 第几页
    
    Returns:
        {list} -- 该页该地点的数据
        {int} -- 该地点结果总数
    """
    # 拼接链接
    url = self.url.format(location, self.key, self.keyword, page)
    # 获得数字签名,并将签名加到链接后面进行请求
    wait_sig = url.split('qq.com')[1] + str(self.sk)
    sig = hashlib.md5(wait_sig.encode('utf-8')).hexdigest()
    res = requests.get(url + '&sig=' + sig)
    # 获得数据返回
    pois = res.json()['data']
    # 避免请求上限
    time.sleep(0.2)
    return pois, res.json()['count'] 

首先是将初始化的请求链接拼接起来,然后由于需要签名校验,因此我们得如下进行操作:

GET请求分为:域名,请求路径和参数三个部分,用于签名计算的有:
请求路径: /ws/place/v1/search?
请求参数: boundary=region({},0)&key={}&keyword={} &page_index={}&page_size=20
注意{}是待填充的

1. 首先对参数进行排序:按参数名升序(本例结果为 boundary 在前,key在后,如果第一个字母相同,要依据第二个字母升序):
boundary=region({},0)&key={}(….后面略)

2. 签名计算(sig):
请求路径+”?”+请求参数+SK进行拼接,并计算拼接后字符串md5值,即为签名(sig):
要求:请求参数必须是未进行任何编码(如urlencode)的原始数据
md5(” /ws/place/v1/search?boundary=region({},0)&key={}&keyword={} &page_index={}&page_size=20你的SK“)

计算得到结果类似为:22dxxxxxxxxxxxxxx2b0bcc0e50

3. 生成最终请求:将计算得到的签名sig,放到请求中(参数名即为:sig):
https://apis.map.qq.com/ws/place/v1/search? boundary=region({},0)&key={}&keyword={} &page_index={}&page_size=20&sig= 22dxxxxxxxxxxxxxx2b0bcc0e50

注意:计算 sig 要使用原始参数值,不要进行任何编码,但最终发送时的参数,是需要时行url编码的

最后拿到返回的值,里面带有所有结果的地理位置及结果的数量。

2.2 按地点返回结果

这一部分其实很简单,就是调用2.1的函数,然后实现分页保存变量,最后输出门店数量,返回数据。

def get_single_location(self, location: str):
    """
    获得单个地点的数据
    
    Arguments:
        location {str} -- 地点
    
    Returns:
        {list} -- 该地点某关键词的所有数据
        {int} -- 该地点某关键词的所有数量
    """
    page = 1
    location_data = []
    pois, total = self.request_data(location, page)
    for poisition in pois:
        location_data.append(poisition)
    # 如果有多页
    while (total / 20) > page:
        pois, _ = self.request_data(location, page)
        for poisition in pois:
            location_data.append(poisition)
        page += 1
    print(f'{self.keyword} {location} 门店总数为:{total}')
    return location_data, total 

计算一线城市的结果如下:

F:\push\20200315>python scrapy.py
瑞幸咖啡 北京 门店总数为:492
瑞幸咖啡 上海 门店总数为:581
瑞幸咖啡 广州 门店总数为:301
瑞幸咖啡 深圳 门店总数为:260

2.3 汇总结果并保存

接下来我们需要汇总2.2计算到的每个城市的数据,保存到json文件,并计算总数。

def get_cities_data(self, cities: str):
    """
    获得所有城市某关键词的数据
    
    Arguments:
        cities {list} -- 城市列表
    """
    result = []
    keyword_count = 0
    for city in cities:
        # 获得该城市的所有门店和总数
        data, count = self.get_single_location(city)
        keyword_count += count
        result.extend(data)
    print(f'{self.keyword} 一线城市门店总数为:{keyword_count}')
    # 导出数据
    with open(f'{self.keyword}.json', 'w') as my_file:
        json.dump(result, my_file, ensure_ascii=False) 

最终可以获得一个 瑞幸咖啡.json 的文件,里面存有每个城市的咖啡店精确位置,并输出一个总数,这样调用即可:

if __name__ == '__main__':
    cities = ['北京', '上海', '广州', '深圳']

    loc = LocationSearch('瑞幸咖啡')
    loc.get_cities_data(cities)

    loc = LocationSearch('星巴克咖啡')
    loc.get_cities_data(cities)

F:\push\20200315>python scrapy.py
瑞幸咖啡 北京 门店总数为:492
瑞幸咖啡 上海 门店总数为:581
瑞幸咖啡 广州 门店总数为:301
瑞幸咖啡 深圳 门店总数为:260
瑞幸咖啡 一线城市门店总数为:1634

星巴克 北京 门店总数为:380
星巴克 上海 门店总数为:797
星巴克 广州 门店总数为:209
星巴克 深圳 门店总数为:201
星巴克 一线城市门店总数为:1587

看来瑞幸咖啡一线城市里的门店数量已经超过星巴克了,不愧是割资本主义国家韭菜,造福中国老百姓的企业啊!

3.扩展

就像文章开头所提到的,如果你需要算出每个城市的咖啡店数量其实也很简单,咱可以调用下面这个接口请求腾讯地图的所有行政区数据,获得所有城市的名称:

https://apis.map.qq.com/ws/district/v1/list

不过我已经dump了一个,大家在Python实用宝典公众号后台回复:咖啡门店数 即可获得。

使用这一个,你只需要读取该csv文件提取所有城市名,然后放入cities变量中进行计算,如下代码所示:

if __name__ == '__main__':
    with open('cities.csv', 'r', encoding='utf-8') as csvfile:
        reader = csv.reader(csvfile)
        cities = [row[0] for row in reader]

    loc = LocationSearch('瑞幸咖啡')
    loc.get_cities_data(cities)

    loc = LocationSearch('星巴克咖啡')
    loc.get_cities_data(cities)

不过,请注意一些特殊情况,比如说那个城市没有数据的时候,接口可能不会返回date数据,这时候要用字典的get方法进行处理:

# pois = res.json()['data']
pois = res.json().get('data', []) 

不过如果你要计算全国的数据的话,这个方法并不可靠,因为无法避免山寨店的存在,山寨店一样也会被记入到腾讯地图中,而一线城市的监管严格,比较少出现山寨店的情况,因此可以用这个方法计算。

我们的文章到此就结束啦,如果你喜欢我们今天的Python 教程,请持续关注我们,如果对你有帮助,麻烦在下面点一个赞/在看哦有任何问题都可以在下方留言区留言,我们都会耐心解答的!


​Python实用宝典 (pythondict.com)
不只是一个宝典
欢迎关注公众号:Python实用宝典

Python 精美俄罗斯方块开源项目

最近想找一些Python相关的游戏开发例子,正好在itch.io上闲逛看到这个俄罗斯方块项目,瞬间被惊艳到了。作者是 Mikhail ,项目地址是:
tetris_for_two: https://gitlab.com/2pi360/tetris_for_two

1.游戏介绍

下面就给大家介绍一下这个用Python写的俄罗斯方块具体功能。它一共有七个游戏模式:

1. 单人模式
2. 普通双人模式
3. 镜像双人模式(即掉落方块都一样)
4. 双人加速模式(每消去一行都会给对方加速)
5. 双人交换控制模式(一次控制自己的方块,一次控制对方的)
6. 双人平衡模式(会改变对方的容量)
7. 双人单容器模式

没错,是不是被这丰富的游戏模式震惊到了?而且这款游戏的界面设计也是相当简洁舒服(而且玩这样的Python开源游戏,你永远不会被广告气到):

不仅如此,除了wasd和上下左右键,它还支持用游戏手柄(仅一个)进行游戏,并且能切换两个玩家的按键设置:

双人模式类似如下, 非常适合小情侣之间消耗时光哦(如果你们都喜欢玩俄罗斯方块的话)

尤其是双人协作模式,两个人一起解决问题也是增进感情的好方法:

还有其他几种游戏模式,大家可以上 itch 上下载游戏体验,或者在公众号后台回复 俄罗斯方块 下载完整源代码和游戏包(各个系统都有)。

2.源码剖析

当然,我们首要目的还是学习这款游戏的源代码,下面就给大家介绍一些这款游戏的部分核心代码。下载该开源项目后,你会发现它的py文件分布如下:

│ base.py
│ game_modes.py
│ main.py
│ run_to_release.py
│ tetris.py
│ … ….
├─assets
│ … …

└─screens
… …

其中,main.py是程序的入口点,首先看看模块引入,sys的引入是当然的,游戏结束的时候需要调用

sys.exit()

使得Python程序正常退出。pygame是这个游戏的引擎,是一个比较老的基于Python的2D游戏引擎,但也因为存在时间长,所以已经是一个很成熟且易上手的2D游戏开发库 。

作者自己写了两个模块,一个是base,里面有画布配置、按键配置、玩家配置等等一系列游戏的基础设置。而 game_modes 则是七种游戏模式的逻辑所在模块,里头还引用了tetris.py,这个模块定义了整个俄罗斯方块旋转的方法及其数据结构。

不过由于时间关系,我们重点看看base里的主循环main_loop:

pygame.time.Clock() 用于配置游戏的帧数,Clock.tick(frameate) 代表每秒framerate帧运行,也就是说,每秒不会执行超过 framerate 次循环 。这个参数的值,我们可以在主函数里看到是600. 也就是这个循环每秒不会超过600次。

pygame.event.get() 是pygame游戏引擎的事件处理器,它用于处理所有的事件,好像打开大门让所有的人进入,然后我们可以根据事件不同的属性做相应的操作,如 event.type == pgl.KEYDOWN 表示键盘被按下时,执行条件中的语句:

pressed_keys.add(event.key) 

于是便将其加入到pressed_keys集合中,yield返回生成器,也就是说只要程序不被终止,这个函数就会不断地返回四个值: events, time_passed, pressed_keys 或 {(0, 0)}。events就是用户触发的事件,time_passed就是这些事件的时长,pressed_keys即用户按下的键。

这样就完成了一次用户事件的传递,然后再又后端对用户的事件进行处理,展示在游戏当中。当然,更复杂的还在后面,这里只是一个简单的事件处理,当然也是最重要的事件处理部分,如果大家有兴趣的话,可以 在公众号后台回复 俄罗斯方块 下载完整源代码进行学习。

我们的文章到此就结束啦,如果你喜欢我们今天的Python 教程,请持续关注我们,如果对你有帮助,麻烦在下面点一个赞/在看哦有任何问题都可以在下方留言区留言,我们都会耐心解答的!


​Python实用宝典 (pythondict.com)
不只是一个宝典
欢迎关注公众号:Python实用宝典

Python 机器学习预测泰坦尼克号存活概率

在泰坦尼克号上你能活下来吗?Python告诉你!

泰坦尼克号是英国的一艘客轮,在1912年4月的一个清晨,其从南安普顿出发,在行驶至目的地纽约的途中与冰山相撞后沉没,船上估计共有2224名乘客和船员,死亡1500多人,成为现代历史上最严重的和平时期海上灾难。

今天,我们将在著名的泰坦尼克号数据集上创建机器学习模型,这个数据集提供了有关泰坦尼克号上乘客的数据,比如经济状况、性别、年龄等等,让我们组合这些特征,构建一个根据参数预测某些人是否能够在当时那种情况下存活的机器学习模型,甚至可以用来测测自己存活的概率。

1.准备

开始之前,你要确保Python和pip已经成功安装在电脑上噢,如果没有,请访问这篇文章:超详细Python安装指南 进行安装。

Windows环境下打开Cmd(开始—运行—CMD),苹果系统环境下请打开Terminal(command+空格输入Terminal),准备开始输入命令安装依赖。

当然,我更推荐大家用VSCode编辑器,把本文代码Copy下来,在编辑器下方的终端装依赖模块,多舒服的一件事啊:Python 编程的最好搭档—VSCode 详细指南

输入以下命令安装我们所需要的依赖模块:

pip install numpy
pip install pandas
pip install seaborn
pip install matplotlib
pip install scikit-learn

看到 Successfully installed xxx 则说明安装成功。啊,别忘了,还要下载数据集,你可以上kaggle官网进行下载,也可以在Python实用宝典公众号后台回复:泰坦尼克号 获得本文完整数据和代码。

2.分析基本数据

在开始使用机器学习进行分析前,我们需要先做一些常规的数据分析,比如缺失值检测、特征数量、基本关联分析等。

2.1 缺失值

首先是缺失值检测,这样的数据集不可能没有缺失值,我们在开始机器学习分析之前就应该把缺失的数据情况分析清楚。

这时候就要善用工具了:7行代码巧用Python热力图可视化表格缺失数据,丰富的知识积累在这个时候就能派上用场。生成热力图:

可见,cabin和Age的缺失值最多,这两列数据到了不得已的情况的话需要删除掉。还有Embarked有几个缺失值,这种情况好处理,我们用填充的方法就可以解决。热力图代码:

2.2 找到特征变量

这一小节,我们重点要找出哪些变量能使得乘客的存活率更高,比如年龄和性别、上船的位置、等等。

首先从年龄、性别上进行分析,根据训练集绘制如下的分析图:

我们可以看到,男性的死亡率其实更高,大体体现了让女性和儿童先逃亡的原则。对于5到18岁的男性而言,存活下来的几率似乎非常低,不过这可能是因为船上这个年龄段的人数少导致的。

再往下看,客舱等级和上船地点是否会对生存率造成影响?请看下图,Embarked是上船港口,pclass是客舱等级,数字1为头等舱。

可以看到,头等舱乘客的存活率高于其他舱的乘客,而且,C港口上岸的人男性存活概率大于女性,这不得不让人怀疑C港口乘客的品德了。

还有一点,亲戚越多是不是越可能存活呢?

可以看到,亲戚数量在1到3的人最有可能存活,不过,大于3之后的存活率可就不太好看了。

这部分可视化的代码如下:

3.机器学习预测

首先我们得根据刚刚的数据分析进行数据预处理,去除掉对我们模型没有帮助的数据【 乘客ID 】。

此外,【cabin】 实在是缺太多了,我们在这里也把它们都去掉。

【name 】 维度,名字要数字化才能分析,为了简化步骤,这里也去除掉。

还要去掉的一个是【Ticket】,都是唯一值,对我们而言没有意义,去除掉。

3.1 补全缺失数据

当然还得补完整我们的缺失值。根据年龄的平均值和标准差求得年龄的随机数,填充缺失的年龄数据。登船点均用S地来替代。

3.2 数字化数据

这里我们一共需要数字化三个维度:

1.票价,从浮点型转整形
2.性别转数字
3.上岸点转数字

不得不说,pandas是真的方便。Map就完事了。

3.3 单值转段值

由于年龄是一个一个的数字,在数据量不够大的情况,这样一个一个的数字没太大意义,我们要按照年龄段进行划分,票价也是如此,我们一起转化了:

3.4 创建模型

终于到了关键点了,然而这里是整个第三节最简单的部分,因为sklearn模块已经帮我们包装好了所有需要做的东西,我们需要做的仅仅是调用模块、传入数据训练、测试。

我们使用随机森林模型(说实话如果没有sklearn,这个模型能写到我头秃),关于随机森林的介绍可以看这一篇文章,其实就是解决了决策树的过拟合问题,这篇文章讲得通俗易懂:
https://blog.csdn.net/mao_xiao_feng/article/details/52728164

训练和测试的代码如下:

准确率如下:

>> python 1.p
0.9034792368125701

准确率有90%,这是挺高的准确率了,让我们把自己的情况带入进去,看看能不能存活,最终数据格式是这样的,你只需要把自己的情况带入,然后往测试数据追加属于你的一行即可:

比如我应该会坐二等舱(其实是三等舱,但是想想我都坐泰坦尼克号了为什么不坐二等舱?);Sex为 1 (男性),Age在范围 3 中(老了啊);SibSp是在船兄弟姐妹配偶的数量,Parch是在船父母、儿女数量,由于我可能是一个人出游,这里我们都设为 0,然后票价Fare应该是 2,Embarked随意选0.

>> python 1.py
1

天啊,我竟然能活下来,不容易 (滑稽,不知道是不是换了个舱的缘故) 。大家也试试看吧。完整代码太长了,在这里就不放出来了,大家可在Python实用宝典公众号后台回复 泰坦尼克号 获取。

本文参考自 https://towardsdatascience.com/predicting-the-survival-of-titanic-passengers-30870ccc7e8

我们的文章到此就结束啦,如果你喜欢我们今天的Python 教程,请持续关注我们,如果对你有帮助,麻烦在下面点一个赞/在看哦有任何问题都可以在下方留言区留言,我们都会耐心解答的!


​Python实用宝典 (pythondict.com)
不只是一个宝典
欢迎关注公众号:Python实用宝典

Python 一键吸猫!找出磁盘里所有猫照

最近在整理我磁盘上的照片,发现不少猫照,突然觉得若能把这些猫照都挑出来,观察它们的成长轨迹也是一件不错的事情。一张一张的找实在是太费劲了,能不能自动化地找出来呢?

目标检测,是许多计算机视觉应用的重中之重,比如说我们上次的实例分割:Python 20行代码批量自动抠图,人体关键点提取、人脸识别等。而我们这一次,是要识别猫照。由于时间不多,我们没有时间收集训练集,那么有没有已经训练好的目标检测模型呢?

这时候就要搬出paddlehub了,puddlehub有一个模型叫做YOLOv3,基于 Joseph Redmon和Ali Farhadi提出的单阶段检测器。该检测器与达到同样精度的传统目标检测方法相比,推断速度能达到接近两倍。

YOLOv3将输入图像分成S*S个格子,每个格子预测B个bounding box,每个bounding box预测内容包括: Location(x, y, w, h)、Confidence Score和C个类别的概率,因此我们不仅能够找出猫的照片,还能定位它的位置!甚至能自动数出一张照片里有多少只猫!

1.准备

为了实现这个实验,Python是必不可少的,如果你还没有安装Python,建议阅读我们的这篇文章哦:超详细Python安装指南

然后,我们需要安装百度的paddlepaddle, 进入他们的官方网站就有详细的指引:
https://www.paddlepaddle.org.cn/install/quick

根据你自己的情况选择这些选项,最后一个CUDA版本,由于本实验不需要训练数据,也不需要太大的计算量,所以直接选择CPU版本即可。选择完毕,下方会出现安装指引,不得不说,Paddlepaddle这些方面做的还是比较贴心的(就是名字起的不好)

不过虽然它里面写了这么多,大部分人用一句话安装,打开CMD(Win+R)或者Terminal(Command+空格搜索)输入以下命令即可安装:

pip install paddlepaddle -i https://mirror.baidu.com/pypi/simple

还需要安装paddlehub,这点别忘了:

pip install -i https://mirror.baidu.com/pypi/simple paddlehub

2.编写代码

我们先试试单图片识别,找到猫猫:

新建predict.py文件,存放猫照在当前文件夹的imgs文件夹下,命名为c1.jpg. 输入以下代码:

import paddlehub as hub

# 加载模型
yolov3 = hub.Module(name="yolov3_darknet53_coco2017")

# 图片位置
test_img_path = "imgs/c1.jpg"

# 输入图片
input_dict = {"image": [test_img_path]}

# 输出结果
results = yolov3.object_detection(data=input_dict)
for result in results:
    print(result['path'])
    print(result['data']) 

在终端/CMD输入以下命令运行文件:

>> python predict.py
[{'left': 684.79376, 'right': 2024.4724, 'top': 961.53644, 'bottom': 2299.855, 'label': 'cat', 'confidence': 0.94765514}, {'left': 1461.0829, 'right': 3853.3633, 'top': 621.53064, 'bottom': 2769.5376, 'label': 'cat', 'confidence': 0.8093604}]

可以看到,识别到了两只猫,其中第一只猫顶部位置为961,右部位置为2024,左部位置为684,底部位置为2299。根据这个位置,可以用框框标记出两只猫:

编写代码,用于框出相应位置的猫:

def paint_rect(input_img: str, output_path: str,
               labels: list, position: list):
    """
    画出矩形
        :param input_img: 输入图片
        :param output_path: 输出图片
        :param labels: 标签
        :param positions: 坐标
    """
    img = cv2.imread(input_img)

    for position in positions:
        print(position)
        # 画矩形框, 输入参数分别为图像、左上角坐标、右下角坐标、颜色数组、粗细
        cv2.rectangle(
            img, (position['left'], position['top']),
            (position['right'], position['bottom']),
            (0, 255, 0), thickness=10
        )

    if 'cat' in labels:
        # 若是猫,则存到另一个地方
        shutil.move(input_img, output_path + os.sep + input_img.split('/')[-1])
        cv2.imwrite(output_path + os.sep + 'rect_%s' % input_img.split('/')[-1], img) 

3.批量自动识别

这样,我们就有思路进行自动识别了,首先获得该文件夹下所有的图片,其次,将这些图片都放入分类器中进行分类,最后,再根据分类的标签将其提取出来移动到其他地方。

获得该文件夹下所有图片:

def get_all_path(dirpath, *suffix):
    """
    获得所有路径

    @param dirpath: 目录
    @param *suffix: 后缀
    """

    path_array = []
    for r, ds, fs in os.walk(dirpath):
        for fn in fs:
            if os.path.splitext(fn)[1] in suffix:
                fname = os.path.join(r, fn)
                path_array.append(fname)
    return path_array 
# 获得所有jpg和png图片
image_paths = get_all_path(source_path, '.jpg', '.JPG', 'png', 'PNG') 

放入分类器中分类:

# 加载模型
yolov3 = hub.Module(name="yolov3_darknet53_coco2017")
# 输入图片
input_dict = {"image": image_paths}
# 输出结果
results = yolov3.object_detection(data=input_dict, labels=['cat']) 

根据标签画框并移动:

def paint_rect(input_img: str, output_path: str,
               labels: list, position: list):
    """
    画出矩形
        :param input_img: 输入图片
        :param output_path: 输出图片
        :param labels: 标签
        :param positions: 坐标
    """
    img = cv2.imread(input_img)

    for position in positions:
        # 画矩形框, 输入参数分别为图像、左上角坐标、右下角坐标、颜色数组、粗细
        cv2.rectangle(
            img, (position['left'], position['top']),
            (position['right'], position['bottom']),
            (0, 255, 0), thickness=10
        )

    if 'cat' in labels:
        # 若是猫,则存到另一个地方
        shutil.move(input_img, output_path + os.sep + input_img.split('/')[-1])
        cv2.imwrite(output_path + os.sep + 'rect_%s' % input_img.split('/')[-1], img) 

results = yolov3.object_detection(data=input_dict, labels=['cat'])
for result in results:
    path = result['path']
    labels = []
    positions = []
    for target in result['data']:
        labels.append(target.get('label', ''))
        positions.append({
            'left': target.get('left', -1),
            'top': target.get('top', -1),
            'right': target.get('right', -1),
            'bottom': target.get('bottom', -1)
        })
    paint_rect(path, target_path, labels, positions)  

完整代码如下,希望大家都能成功提取出自己的“猫片”:

import paddlehub as hub
import cv2
import os
import shutil


def get_all_path(dirpath, *suffix):
    """
    获得所有路径

    @param dirpath: 目录
    @param *suffix: 后缀
    """

    path_array = []
    for r, ds, fs in os.walk(dirpath):
        for fn in fs:
            if os.path.splitext(fn)[1] in suffix:
                fname = os.path.join(r, fn)
                path_array.append(fname)
    return path_array


def paint_rect(input_img: str, output_path: str,
               labels: list, position: list):
    """
    画出矩形
        :param input_img: 输入图片
        :param output_path: 输出图片
        :param labels: 标签
        :param positions: 坐标
    """
    img = cv2.imread(input_img)

    for position in positions:
        # 画矩形框, 输入参数分别为图像、左上角坐标、右下角坐标、颜色数组、粗细
        cv2.rectangle(
            img, (position['left'], position['top']),
            (position['right'], position['bottom']),
            (0, 255, 0), thickness=10
        )

    if 'cat' in labels:
        # 若是猫,则存到另一个地方
        shutil.move(input_img, output_path + os.sep + input_img.split('/')[-1])
        cv2.imwrite(output_path + os.sep + 'rect_%s' % input_img.split('/')[-1], img)


if __name__ == '__main__':
    source_path = './imgs/'
    target_path = './target/'

    # 获得所有jpg和png图片
    image_paths = get_all_path(source_path, '.jpg', '.JPG', 'png', 'PNG')

    # 加载模型
    yolov3 = hub.Module(name="yolov3_darknet53_coco2017")

    # 输入图片
    input_dict = {"image": image_paths}

    # 输出结果
    results = yolov3.object_detection(data=input_dict, labels=['cat'])
    for result in results:
        path = result['path']
        labels = []
        positions = []
        for target in result['data']:
            labels.append(target.get('label', ''))
            positions.append({
                'left': target.get('left', -1),
                'top': target.get('top', -1),
                'right': target.get('right', -1),
                'bottom': target.get('bottom', -1)
            })
        paint_rect(path, target_path, labels, positions)

我们的文章到此就结束啦,如果你希望我们今天的Python 教程,请持续关注我们,如果对你有帮助,麻烦在下面点一个赞/在看哦有任何问题都可以在下方留言区留言,我们都会耐心解答的!


​Python实用宝典 (pythondict.com)
不只是一个宝典
欢迎关注公众号:Python实用宝典

AO3被封的冤不冤?可视化数据分析《下坠》

AO3是一个外网自由创作网站,全称为 Archive of Our Own 其在Alexa的世界排名居于第690名,是雨果最佳相关作品奖的获得者。作为一个非盈利性的开源同人小说数据库网站,站内的文章均由网友贡献,因此也没有核查机制。

1月30日,网友“博君一肖”在AO3发布并连载了一篇同人文《下坠》,并在微博同步上传了这篇文章,而且自设了预警,希望接受不了的人不要点开。

几天后,这篇文章连载到12章,而且微博原文包含了ao3网站和lofter app链接,引起了大量博肖cp粉热转。

26日,许多粉丝觉得该cp文中含有侮辱性文字,无法接受这样的文字,于是开始撕X,网上举报阵营和lof阵营开始对线,互相口吐芬芳,展现了中华民族几千年来的文化底蕴。

事件持续发酵,最终闹到了某办,某办一看,我X,原来还有这个漏网之鱼,顺手就给他封了。真的太冤了,不过也不能说人家乱封,为什么呢?因为同人文大多是读者在原作的基础上把某些作品里的人物放在新的环境里,以展现自己和原作不同的观念,而大多数时候,这些观念最终都会掺杂色情因素。看看我们下文对《下坠》的分析就知道了。

本文完整分析代码可在公众号后台回复:下坠 获得。本文不详细分析代码,不过这份代码的知识,你可以在这两篇文章里学习到:

1. Python 情人节超强技能 导出微信聊天记录生成词云

2. Python 识别文本情感就这么简单

1.词频统计

我们利用Python里的jieba分词、matplotlib模块分析整篇文章词汇,并提取词频前20的词语,得到结果如下:

确实,涉及到两位明星的词语是最多的,其次是阿丽姐(不知道是不是作者的化身)。赞赞在其中是女性角色,难怪粉丝们暴跳如雷。这样分析,似乎看不出太多的内含,我们把维度细化一点。

从敏感角度看,这个词汇频率会是怎样的呢?由于纯洁的我实在是接受不了,因此打了点马赛克(如果这样你都能猜出是什么词….嗯…建议多看看天线宝宝):

经过统计,文章出现一共20367个非黄色词汇,284个涉黄词汇。涉黄词汇出现概率约为1.4%,也就是说每100个词汇里就会出现一次黄词,这个概率相当高了,感觉《挪威的森林》略逊一筹,《失乐园》大可一战。

最后,来个词云结束这一部分:

2.句型分析

我们使用Lstm,按行对整片文章进行分析,看看这些句子呈现的情感特点是否有某边倒的倾向,其中,当分为正面信度大于0.7,或负面信度大于0.7的时候分别分到正面分类和负面分类,其他情况为中性:

得到结果如下:

>>{‘neg’: 988, ‘pos’: 332, ‘mid’: 471}

负面的句子占了55%,文章负面情绪较多。负面情绪只是衡量一篇文章的情感倾向,无法说明什么。

接下来才是关键,识别句子的涉黄程度,同样地,设定概率置信度大于0.7的时候进行分类:

获得结果如下:

>> {‘porn’: 280, ‘not_porn’: 1511}

1800条句子中,280条语句涉黄,概率高达16%. 每100条句子中就有约16条黄色片段,《失乐园》可能都甘拜下风啊。到这里,大家可能都会觉得这篇同人文被举报是非常正常的(尽管粉丝们不满的是某位明星被当成女性角色)。

当然,大家如果感兴趣还可以用词法分析工具分析文章中的攻防次数,非常有意思,但是涉及到敏感词汇,我这里就不再展开了(逃)。本文完整分析代码可在公众号后台回复:下坠 获得。

我们的文章到此就结束啦,如果你希望我们今天的Python 教程,请持续关注我们,如果对你有帮助,麻烦在下面点一个赞/在看哦有任何问题都可以在下方留言区留言,我们都会耐心解答的!


​Python实用宝典 (pythondict.com)
不只是一个宝典
欢迎关注公众号:Python实用宝典

你的10W块放哪里能赚最多钱?

现在许多人都想学会理财并进行适当的投资,从而增加“睡后收入”,迈向财务自由。说到投资,最经典的当然是股市了,但股市对于大部分人而言是烫手山芋,无法从中获得稳定的收益。因此,对于大部分人而言,最好的投资产品还是基金。

​基金分为好几种,因此收益的计算公式也分许多种,我们这里介绍三种最常见的收益计算方式,从而找到收益最高的那种基金:

第一种是七日年化收益。最常见的是余某宝和一些理财基金。

第二种是每日万份收益。许多产品可能会用它作为指标。

第三种是定投基金。大多是一些股票投资组合基金,比理财基金风险高,但也是最值得投资的,请往后看。

1.余某宝

我们先尝试利用七日年化收益算算余某宝现在的收益,这可是这些年的明星产品啊,今天2020年2月27日的七日年化收益率为2.306%:

觉得我穷的就赞赏一个吧,嘻嘻

七日年化收益的计算方法是这样的:
当日收益 = 金额 X 7日年化 ÷ 360。

Python 计算代码计算最终收益:

假设我们投入10W元,放180天:

>> profit_7_days(100000, 0.023, 180)
(101156.60076153441, 1156.6007615344133)

最终利润为1156元,太少了,这个利润绝对跑不过CPI,要知道,2020年1月份CPI同比上涨5.4%哦。当然,还是比放银行活期好得多。

2.活期理财

市面上还有许多保守型活期/定期理财,我们选最高利率的一种来试一下,这一个采用万份收益来计算:

万份收益的计算公式如下:
当日收益 = 金额 ÷ 10000 X 当日万份收益。

Python代码如下:

假设我们投入10W元,放180天:

>> profit_10_thousand(100000, 1.0485, 180)
(101905.12125702304, 1905.1212570230418)

哎,比余额宝好不了多少嘛,那我还不如继续用余额宝。

3.定投基金

定投基金比较有意思,是我们今天的主角。它属于“保守版”的​高风险投资,因为分散投资能够有效规避风险,面对股市无常的变化,定投的基金并不会产生太大的影响,所以相对安全,收益也相对稳定。

它的计算公式如下:

M=a(1+b)[-1+(1+b)^n]/b

其中:
1. M表示定投n年后总金额(包括收益和本金);
2. a表示每年投入的金额(比如每月投入1200元,a=14400元);
3. b表示年收益率(比如年收益为50%,其b=0.5);
4. ^n表示n次方。

比如这一款基金,最近三年涨跌幅分别为:69.07%, 51.3%, 66.3%. 平均下来年涨跌幅为62%,非常可怕:

不过今年由于疫情影响,估计最终收益会低许多,我们算40%的年收益率吧。

Python代码如下:

假设我们每个月投一万块钱,持续一年:

>> profit_investment_plan(10000, 0.40, 1)
(167999.99999999994, 47999.99999999994, 0.8117274492919773)

没错,最终赚了约4.8W,其第一年真实的年化收益率为 81%,如果第一年结束取出来,其总利率达到了 47999/167999 = 28.5%.

原来,基金定投才是投资的最好姿势啊!不过,收益越高,风险越高,虽然基金定投能够很好地避免股市波动,但是它还是存在不小的风险的。

如果想获得稳健的收益,个人建议你需要将钱放在不同的篮子里以规避风险,比如每月收入的30%定投基金,20%理财基金,10%指数型基金,20%债券基金,20%活期基金(如余额宝之类)。当然,最适合的搭配要根据个人收入进行组合。

市面上有许多可靠的基金定投,只要选择那种最近几年没有负收益的,遇到市场形式较好的时候,基本上收益都能跑得过CPI,微X的某财通里就有很多,为了避免广告嫌疑,这里就不再多介绍啦。本文全部的计算代码,可在公众号后台回复 基金投资计算 获得。

我们的文章到此就结束啦,如果你希望我们今天的Python 教程,请持续关注我们,如果对你有帮助,麻烦在下面点一个赞/在看哦有任何问题都可以在下方留言区留言,我们都会耐心解答的!


​Python实用宝典 (pythondict.com)
不只是一个宝典
欢迎关注公众号:Python实用宝典

Python 批量修改图片亮度和饱和度

在Photoshop里也可以做到批量修改图片的亮度和饱和度,但是很多人都没有条件使用Photoshop,此外,Photoshop里的批量修改其实很耗性能,而且使用起来并不是很方便。

那我们能不能用Python做一个小工具,先找到合适的亮度和饱和度,然后再根据这个指定的值对所有需要做相似调整的图片做批量修改呢?答案是肯定的。

1.准备

开始之前,你要确保Python和pip已经成功安装在电脑上噢,如果没有,请访问这篇文章:超详细Python安装指南 进行安装。

Windows环境下打开Cmd(开始—运行—CMD),苹果系统环境下请打开Terminal(command+空格输入Terminal). 输入以下命令安装我们所需要的模块:

pip install numpy
pip install opencv-python

看到 Successfully installed xxx 则说明安装成功。

2.开发调整工具

这一部分,我们将开发出一个能够调整图像亮度和饱和度的工具,而且这个工具支持滑动调整。其实放到别的语言里,这可是个小工程,但是放到Python里,我们用50行代码就能解决了。

首先是加载图片,然后需要将图片转化为HLS模式才能够调整亮度和饱和度。这是因为默认的图片颜色空间是RGB,它非常适合显示器显示,但由于只有三个颜色分类,并不适合图像处理。而HLS模式相对于RGB颜色空间则复杂得多,HLS分别代表H: Hue(色调),L: Lightness(亮度), S: Saturation(饱和度)。

其颜色空间是一个三维空间,如下图所示:

这样的颜色空间才使得我们可以调整图片的细节部分。Python代码中,将RGB转化为HLS空间是很简单的,两行代码就能做到:

import numpy as np
import cv2

# 加载图片 读取彩色图像归一化且转换为浮点型
image = cv2.imread('2.jpg', cv2.IMREAD_COLOR).astype(np.float32) / 255.0

# 颜色空间转换 BGR转为HLS
hlsImg = cv2.cvtColor(image, cv2.COLOR_BGR2HLS)

然后我们需要做两个滑动块,一个调节亮度,一个调节饱和度:

# 滑动条最大值
MAX_VALUE = 100
# 滑动条最小值
MIN_VALUE = 0

# 调节饱和度和亮度的窗口
cv2.namedWindow("lightness and saturation", cv2.WINDOW_GUI_NORMAL)

# 创建滑动块
cv2.createTrackbar("lightness", "lightness and saturation", MIN_VALUE, MAX_VALUE, lambda x:x)
cv2.createTrackbar("saturation", "lightness and saturation", MIN_VALUE, MAX_VALUE, lambda x:x)

调节前还需要保存一下原图,所以我们会在内存里复制一个新的变量用于调节图片,然后获得两个滑动块的值,再根据值进行亮度和饱和度的调整:

# 调整饱和度和亮度
while True:
    # 复制原图
    hlsCopy = np.copy(hlsImg)
    # 得到 lightness 和 saturation 的值
    lightness = cv2.getTrackbarPos('lightness', 'lightness and saturation')
    saturation = cv2.getTrackbarPos('saturation', 'lightness and saturation')
    # 1.调整亮度(线性变换)
    hlsCopy[:, :, 1] = (1.0 + lightness / float(MAX_VALUE)) * hlsCopy[:, :, 1]
    hlsCopy[:, :, 1][hlsCopy[:, :, 1] > 1] = 1
    # 饱和度
    hlsCopy[:, :, 2] = (1.0 + saturation / float(MAX_VALUE)) * hlsCopy[:, :, 2]
    hlsCopy[:, :, 2][hlsCopy[:, :, 2] > 1] = 1
    # HLS2BGR
    lsImg = cv2.cvtColor(hlsCopy, cv2.COLOR_HLS2BGR)
    # 显示调整后的效果
    cv2.imshow("lightness and saturation", lsImg)

效果如下图所示:

到这里还不够,由于是while循环支持的调节,我们还需要让其可以退出和保存:

    ch = cv2.waitKey(5)
    # 按 ESC 键退出
    if ch == 27:
        break
    elif ch == ord('s'):
        # 按 s 键保存并退出
        lsImg = lsImg * 255
        lsImg = lsImg.astype(np.uint8)
        cv2.imwrite("lsImg.jpg", lsImg)
        break

这样,按s键可以保存图片并退出,按ESC键可以直接退出编辑器。 完整文字版50行代码请在Python实用宝典公众号后台回复:批量修改图片 获得。

3.批量修改

前面根据我们的小工具获得了需要的饱和度和亮度,把这对值记下来就可以批量修改图片了。当然,我们没有自动批量修改到正确值这么逆天的功能,这个工具只适合相同场景下,能够用同一对亮度和饱和度进行调整的图片:

def update(input_img_path, output_img_path, lightness, saturation):
    """
    用于修改图片的亮度和饱和度
    :param input_img_path: 图片路径
    :param output_img_path: 输出图片路径
    :param lightness: 亮度
    :param saturation: 饱和度
    """

    # 加载图片 读取彩色图像归一化且转换为浮点型
    image = cv2.imread(input_img_path, cv2.IMREAD_COLOR).astype(np.float32) / 255.0

    # 颜色空间转换 BGR转为HLS
    hlsImg = cv2.cvtColor(image, cv2.COLOR_BGR2HLS)

    # 1.调整亮度(线性变换)
    hlsImg[:, :, 1] = (1.0 + lightness / float(MAX_VALUE)) * hlsImg[:, :, 1]
    hlsImg[:, :, 1][hlsImg[:, :, 1] > 1] = 1
    # 饱和度
    hlsImg[:, :, 2] = (1.0 + saturation / float(MAX_VALUE)) * hlsImg[:, :, 2]
    hlsImg[:, :, 2][hlsImg[:, :, 2] > 1] = 1
    # HLS2BGR
    lsImg = cv2.cvtColor(hlsImg, cv2.COLOR_HLS2BGR) * 255
    lsImg = lsImg.astype(np.uint8)
    cv2.imwrite(output_img_path, lsImg)

这部分其实比制作刚刚的工具简单,可以说是工具的简化版。分为以下六个步骤:

1.加载图片。
2.转化为HLS空间。
3.调整亮度。
4.调整饱和度。
5.转化为RGB空间。
6.保存。

然后我们只需要批量地将图片传入该函数,就能实现批量转化:

dataset_dir = 'imgs'
output_dir = 'output'
lightness = 10
saturation = 20

# 获得需要转化的图片路径, 并生成目标路径
image_filenames = [(os.path.join(dataset_dir, x), os.path.join(output_dir, x))
                    for x in os.listdir(dataset_dir)]
# 转化所有图片
for path in image_filenames:
    update(path[0], path[1], lightness, saturation)

通过这份Python代码,你能在1分钟内修改几千张图片,这样的效率并非Photoshop能比的。当然,它也有它的缺点,那就是只能根据你输入的值进行修改,而Photoshop能够进行自动优化(虽然精度评价因人而异)。

我们的文章到此就结束啦,如果你希望我们今天的Python 教程,请持续关注我们,如果对你有帮助,麻烦在下面点一个赞/在看哦有任何问题都可以在下方留言区留言,我们都会耐心解答的!


​Python实用宝典 (pythondict.com)
不只是一个宝典
欢迎关注公众号:Python实用宝典

Python 识别文本情感就这么简单

很多同学都对自然语言处理感兴趣,但是却不知道应该从哪里下手。Python实用宝典曾写过一篇文章(《短文本分类识别自杀倾向》),教你从构建数据集到训练数据,再到测试数据,整个流程确实需要耐心的人才能成功走通。

不过现在有了paddlehub,我们可以先省略掉构建数据集和训练数据这两个步骤,直接拿模型过来文本分类

一旦简单版的分类成功了,你就会有动力继续前进,继续学习如何训练属于自己的模型。

今天我们用paddlehub中比较简单的情感倾向分析模型 senta_lstm 来对文本做一个简单的积极和消极的分类。

1.准备

为了实现这个实验,Python是必不可少的,如果你还没有安装Python,建议阅读我们的这篇文章哦:超详细Python安装指南

然后,我们需要安装百度的paddlepaddle, 进入他们的官方网站就有详细的指引:
https://www.paddlepaddle.org.cn/install/quick

根据你自己的情况选择这些选项,最后一个CUDA版本,由于本实验不需要训练数据,也不需要太大的计算量,所以直接选择CPU版本即可。选择完毕,下方会出现安装指引,不得不说,Paddlepaddle这些方面做的还是比较贴心的(就是名字起的不好)

不过虽然它里面写了这么多,大部分人用一句话安装,打开CMD(Win+R)或者Terminal(Command+空格搜索)输入以下命令即可安装:

pip install paddlepaddle -i https://mirror.baidu.com/pypi/simple

还需要安装paddlehub,这点别忘了:

pip install -i https://mirror.baidu.com/pypi/simple paddlehub

2.编写代码

整个步骤分为三步:

1.加载模型
2.指定待分类文本
3.情感分类

import paddlehub as hub

# 加载模型
senta = hub.Module(name="senta_lstm")

# 待分类文本
test_text = [
    "你长得真好看",
    "《黑色四叶草》是部不错的番"
]

# 情感分类
results = senta.sentiment_classify(data={"text": test_text})

# 得到结果
for result in results:
    print(result)

将这份代码保存为 code.py, (如果你懒得打一遍,可以再公众号后台回复 识别文本情感 获得代码)在CMD或Terminal中进入该文件文件夹运行以下命令执行脚本: python code.py

就能得到以下结果:

{‘text’: ‘你长得真好看’, ‘sentiment_label’: 1, ‘sentiment_key’: ‘positive’, ‘positive_probs’: 0.9866, ‘negative_probs’: 0.0134}
{‘text’: ‘《黑色四叶草》是部不错的番’, ‘sentiment_label’: 1, ‘sentiment_key’: ‘positive’, ‘positive_probs’: 0.9401, ‘negative_probs’: 0.0599}

其中:
1.sentiment_key 代表分类结果,postive是 积极 ,negative是 消极 。
2.sentiment_label 是分类结果标签,1代表 积极 ,0代表 消极 。
3. positive_probs 是积极分类的置信度,0.9866即模型判断98.66%的可能性是正面。
4. negative_probspositive_probs 相对,是消极分类的置信度。

3.结果分析

这么看,你会发现其实在有明显的积极消极词汇面前,这个模型的分类效果还是不错的。那在特殊的例子面前效果又如何呢?我们去微博随便取一条试一下,比如银教授的段子:

分类结果:

{‘text’: ‘他们都网上办公、网上学习了,你什么时候跟我网恋?’, ‘sentiment_label’: 0, ‘sentiment_key’: ‘negative’, ‘positive_probs’: 0.0507, ‘negative_probs’: 0.9493}

竟然意外的分对了。虽然是句段子,但是明显有对方不跟自己网恋的消极态度。再试试有潜在含义的句子:

{‘text’: ‘不想说什么了,听首歌吧。’, ‘sentiment_label’: 0, ‘sentiment_key’: ‘negative’, ‘positive_probs’: 0.0321, ‘negative_probs’: 0.9679}

{‘text’: ‘我忘了世界还有一种人火星人,你从那来的吧。’, ‘sentiment_label’: 1, ‘sentiment_key’: ‘positive’, ‘positive_probs’: 0.7261, ‘negative_probs’: 0.2739}

这里第一句分对了,第二句没分对。确实,第二句太隐晦了,机器可能分不出来。不过,置信度并不高,如果真的需要应用这个模型,可以通过置信度过滤掉一些分类。

总的而言,这个模型效果还是不错的,在网上那么多情感分类开源的模型中,百度的这个应该可以打80分左右。

而且,它支持你自己做一些微调(Fine-tune),也就是能够使用自定义的训练集调整模型到你需要的样子,详见github:
https://github.com/PaddlePaddle/models/tree/develop/PaddleNLP/sentiment_classification

我们的文章到此就结束啦,如果你希望我们今天的Python 教程,请持续关注我们,如果对你有帮助,麻烦在下面点一个赞/在看哦有任何问题都可以在下方留言区留言,我们都会耐心解答的!


​Python实用宝典 (pythondict.com)
不只是一个宝典
欢迎关注公众号:Python实用宝典

有趣,用Python算算哪个星座富豪最多!

最近经常看到关于星座的推送,我其实不信这个,但是由于推送得太多了,总有几篇会让我好奇地点进去看看。然后想想其实用Python写一篇星座相关的文章也不错。

正好,Python计算一个人的星座特别简单,因为每个星座的日期是固定的。我们只需要四行代码就能计算:

def cal_constellation(month, day):
    constellation = (u'摩羯座',u'水瓶座',u'双鱼座',u'白羊座',u'金牛座',u'双子座',u'巨蟹座',u'狮子座',u'处女座',u'天秤座',u'天蝎座',u'射手座')
    start_day = ((1,20),(2,19),(3,21),(4,21),(5,21),(6,22),(7,23),(8,23),(9,23),(10,23),(11,23),(12,23))
    return constellation[len(list(filter(lambda y:y<=(month,day), start_day)))%12]

把出生的月份和日期传入这个函数,就能得到对应的星座了。当然,这只是非常简单的第一步,接下来让我们计算2012全球富豪榜前一百名中,哪个星座的人最多,嘻嘻,期待吗?

1.获得数据

豆瓣上有个帖子帮我们列出了相应的数据,不过是以文本的形式:https://www.douban.com/group/topic/28671832/

幸好有统一的格式,我们能用正则表达式把出生日期提取出来:

(\d+) ?月 ?(\d+) ?日

在Vscode中还能直接用模式替换,变成我们想要的元组形式:

最后发现有出生月日的只有88条,没关系,够我们用了。

2.放入代码计算

将前面获得的所有日期放入数组中,然后调用我们一开始说的星座计算函数即可,当然,需要用一个字典来计算每次星座的出现:

birth_day = [
    (1, 28), (10, 28), (8, 30), (3, 5), (3, 28), (8, 17), (11, 3), (10, 4), (7, 29), (2, 20), (11, 1),
    (5, 3), (8, 4), (10, 21), (7, 7), (10, 7), (10, 28), (4, 19), (2, 14), (6, 15), (8, 12), (4, 26),
    (8, 21), (3, 26), (1, 12), (4, 2), (9, 9), (3, 7), (2, 20), (2, 9), (3, 28), (11, 5), (4, 16), (1, 14),
    (4, 12), (6, 12), (9, 1), (5, 14), (9, 21), (8, 26), (2, 23), (5, 7), (7, 24), (3, 24), (9, 26), (1, 3),
    (2, 24), (1, 21), (7, 8), (2, 16), (8, 16), (10, 10), (9, 1), (4, 21), (5, 3), (4, 28), (8, 21), (12, 1),
    (12, 14), (10, 6), (1, 27), (4, 14), (6, 4), (10, 24), (5, 11), (8, 26), (1, 1), (6, 14), (8, 11), (5, 22),
    (5, 10), (4, 10), (5, 9), (12, 22), (12, 11), (3, 20), (3, 8), (9, 22), (12, 19), (11, 17), (9, 15), (3, 25),
    (2, 7), (4, 4), (4, 1), (6, 2), (2, 13), (11, 8)
]
def cal_constellation(month, day):
    constellation = (u'摩羯座',u'水瓶座',u'双鱼座',u'白羊座',u'金牛座',u'双子座',u'巨蟹座',u'狮子座',u'处女座',u'天秤座',u'天蝎座',u'射手座')
    start_day = ((1,20), (2,19), (3,21), (4,21), (5,21), (6,22), (7,23), (8,23), (9,23), (10,23), (11,23), (12,23))
    return constellation[len(list(filter(lambda y:y<=(month,day), start_day)))%12]

result = {}
for birth in birth_day:
    constel = cal_constellation(birth[0], birth[1])
    if constel not in result:
        result[constel] = 0
    else:
        result[constel] += 1
print(result)

结果如下:

{‘水瓶座’: 7, ‘天蝎座’: 7, ‘处女座’: 8, ‘双鱼座’: 7, ‘白羊座’: 12, ‘狮子座’: 8, ‘天秤座’: 5, ‘金牛座’: 9, ‘巨蟹座’: 1, ‘双子座’: 5, ‘摩羯座’: 3, ‘射手座’: 4}

排个序吧:

print(sorted(result.items(), key=lambda item: item[1]))

结果:

[(‘巨蟹座’, 1), (‘摩羯座’, 3), (‘射手座’, 4), (‘天秤座’, 5), (‘双子座’, 5), (‘水瓶座’, 7), (‘天蝎座’, 7), (‘双鱼座’, 7), (‘处女座’, 8), (‘狮子座’, 8), (‘金牛座’, 9), (‘白羊座’, 12)]

白羊座惊为天人达到了12位。12/88 = 14%啊,这个比例相当牛皮了。然而我的巨蟹座只有1位,枯了,难道我没有成为富豪的天赋??

不过,大家也不要伤心。我们只取了88名富豪的数据还不够多,像这样的数据分析大概要8888名富豪的出生日期才能得到一个比较靠谱的结果。

我们的文章到此就结束啦,如果你希望我们今天的Python 教程,请持续关注我们,如果对你有帮助,麻烦在下面点一个赞/在看哦有任何问题都可以在下方留言区留言,我们都会耐心解答的!


​Python实用宝典 (pythondict.com)
不只是一个宝典
欢迎关注公众号:Python实用宝典