使用张量流代理的强化学习—教程
用这个简单的教程试试 TF-Agents for RL,它以 Google colab 笔记本的形式发布,所以你可以直接从你的浏览器上运行它。
几周前,我写了一篇文章,列举了可以用来在项目中实现强化学习(RL)的不同框架,展示了每个框架的盛衰,并想知道是否有任何一个框架会在某个时候统治所有框架。从那以后,我开始知道了 TF Agents ,这是一个基于 TensorFlow 的 RL 库,并得到了其社区的全力支持(注意,TF Agents 不是 Google 的官方产品,但它是作为 Github 上的官方 TensorFlow 帐户的存储库发布的)。
我目前正在一个项目中使用 TF 代理,由于它的良好文档,包括教程,开始使用它很容易。它定期更新,有许多贡献者,这使我认为我们有可能在不久的将来看到 TF 代理作为实现 RL 的标准框架。正因为如此,我决定写这篇文章给你一个快速的介绍,这样你也可以从这个库受益。我已经发布了这里使用的所有代码,作为一个 Google colab 笔记本,所以你可以很容易地在线运行它。
你可以在这里找到 Github 的所有代码和文档。你不需要克隆他们的库,但是有官方的 Github 作为参考总是有用的。我实现了下面的例子,部分遵循他们的教程(1_dqn_tutorial ),但我进一步简化了它,并在本文中用它来玩 Atari 游戏。让我们动手吧。
安装 TF 代理和依赖项
如前所述,TF-Agents 运行在 TensorFlow 上,更具体地说是 TensorFlow 2.2.0。此外,如果您还没有以下软件包,您需要安装它们:
pip install tensorflow==2.2.0
pip install tf-agents
为 CartPole 实现 DQN 代理
我们将实现一个 DQN 代理( Mnih et al. 2015 ),并将其用于经典控制问题 CartPole。如果你想解决一些更令人兴奋的事情,比如说,一个 Atari 游戏,你只需要从所有可用的 OpenAI 环境中选择一个你想要的环境名。
我们从所有必要的进口开始。正如你在下面看到的,我们从 TF-Agents 实现了相当多的对象。这些都是我们可以为我们的实现定制和切换的东西。
from __future__ import absolute_import, division, print_functionimport base64
import IPython
import matplotlib
import matplotlib.pyplot as plt
import numpy as np
import tensorflow as tffrom tf_agents.agents.dqn import dqn_agent
from tf_agents.drivers import dynamic_step_driver
from tf_agents.environments import suite_gym
from tf_agents.environments import tf_py_environment
from tf_agents.eval import metric_utils
from tf_agents.metrics import tf_metrics
from tf_agents.networks import q_network
from tf_agents.replay_buffers import tf_uniform_replay_buffer
from tf_agents.trajectories import trajectory
from tf_agents.utils import common
环境
OpenAI 健身房的翻筋斗环境[GIF from 积谷康/RL-翻筋斗。]
现在,我们开始创造我们的环境。在 CartPole 中,我们有一个顶部有一根杆子的推车,代理的任务是学习保持杆子,左右移动推车。请注意,我们将使用已经包含在 TF-Agents 中的 suite_gym 中的 e 环境,这是 OpenAI Gym 环境的一个稍微定制(并针对其与 TF-Agents 的使用进行了改进)的版本(如果您感兴趣,可以查看与 OpenAI 的实现这里的差异)。我们还将为我们的环境使用一个名为 TFPyEnvironment 的包装器,它将用于状态观察、操作和奖励的 numpy 数组转换为 TensorFlow 张量。在处理张量流模型(即神经网络)时,我们使用张量,因此通过使用这个包装器,我们可以节省一些转换这些数据所需的工作。
env = suite_gym.load('CartPole-v1')
env = tf_py_environment.TFPyEnvironment(env)
代理人
TF 中有不同的药剂——我们可以使用的药剂: DQN 、增援、 DDPG 、 TD3 、 PPO 和 SAC 。如上所述,我们将使用 DQN。代理的一个主要参数是它的 Q(神经)网络,它将用于计算每一步中动作的 Q 值。q_network 有两个强制参数:定义观察形状和动作形状的 input_tensor_spec 和 action_spec。我们可以从我们的环境中得到这一点,因此我们将我们的 q_network 定义如下:
q_net = q_network.QNetwork(env.observation_spec(),
env.action_spec())
正如你在这里看到的,我们可以为我们的 q_network 定制更多的参数,但是现在,我们将使用默认的参数。代理还需要一个优化器来查找 q_network 参数的值。让我们保持经典,用亚当。
optimizer = tf.compat.v1.train.AdamOptimizer(learning_rate=0.001)
最后,我们用以下参数定义并初始化我们的代理:
- time_step_spec,它是我们从环境中获得的,定义了我们的时间步长是如何定义的。
- action_spec,与 q_network 相同。
- 我们之前创建的 Q 网。
- 我们之前创建的优化器。
- TD 误差损失函数,类似于神经网络中的损失函数。
- 列车步数计数器,这只是一个 0 阶张量(也称为标量),它将计算我们在环境中的步数。
train_step_counter = tf.Variable(0)agent = dqn_agent.DqnAgent(env.time_step_spec(),
env.action_spec(),
q_network=q_net,
optimizer=optimizer,
td_errors_loss_fn=
common.element_wise_squared_loss,
train_step_counter=train_step_counter)agent.initialize()
辅助方法:平均累积回报和收集数据
我们还需要一些辅助方法。第一个将在环境中迭代若干集,应用策略来选择要遵循的操作,并返回这些集中的平均累积奖励。这将有助于评估我们的代理了解到的策略。下面,我们也在我们的环境中尝试该方法 10 集。
def compute_avg_return(environment, policy, num_episodes=10):
total_return = 0.0
for _ in range(num_episodes):
time_step = environment.reset()
episode_return = 0.0 while not time_step.is_last():
action_step = policy.action(time_step)
time_step = environment.step(action_step.action)
episode_return += time_step.reward
total_return += episode_return avg_return = total_return / num_episodes
return avg_return.numpy()[0]# Evaluate the agent's policy once before training.
avg_return = compute_avg_return(env, agent.policy, 5)
returns = [avg_return]
我们还将在培训我们的代理时实现一种收集数据的方法。DQN 的突破之一是经验回放,我们将代理人的经验(状态、动作、奖励)存储起来,用它在每一步批量训练 Q 网络。这通过使学习更快和更稳定来改进学习。为了做到这一点,TF-Agents 包含了 TFUniformReplayBuffer 对象,它存储了这些经验以便以后重用,所以我们首先创建这个我们以后会用到的对象。
在这种方法中,我们采用一个环境、一个策略和一个缓冲区,采用由它的状态观察和奖励形成的当前时间步长、策略选择的动作以及下一个时间步长。然后,我们将它存储在重放缓冲区中。注意,重放缓冲区存储了一个名为 Trajectory 的对象,所以我们用前面命名的元素创建了这个对象,然后使用 add_batch 方法将它保存到缓冲区。
replay_buffer = tf_uniform_replay_buffer.TFUniformReplayBuffer(
data_spec=agent.collect_data_spec,
batch_size=env.batch_size,
max_length=100000)def collect_step(environment, policy, buffer):
time_step = environment.current_time_step()
action_step = policy.action(time_step)
next_time_step = environment.step(action_step.action)
traj = trajectory.from_transition(time_step,
action_step,
next_time_step)# Add trajectory to the replay buffer
buffer.add_batch(traj)
列车代理
我们终于可以训练我们的特工了。我们定义了我们在每一次迭代中的步数,在这个步数之后,我们将在每一次迭代中训练我们的代理,修改它的策略。现在让我们每次迭代只使用一步。我们还定义了我们的 Q 网络将被训练的批量大小和一个迭代器,以便我们迭代代理的经验。
然后,我们将为缓冲器收集一些经验,并从常见的 RL 环路开始。通过对环境采取行动、培训政策和重复来获得经验。我们另外打印损失,并分别每 200 和 1000 步评估代理的性能。
collect_steps_per_iteration = 1
batch_size = 64
dataset = replay_buffer.as_dataset(num_parallel_calls=3,
sample_batch_size=batch_size,
num_steps=2).prefetch(3)
iterator = iter(dataset)
num_iterations = 20000
env.reset()for _ in range(batch_size):
collect_step(env, agent.policy, replay_buffer)for _ in range(num_iterations):
# Collect a few steps using collect_policy and save to the replay buffer.
for _ in range(collect_steps_per_iteration):
collect_step(env, agent.collect_policy, replay_buffer) # Sample a batch of data from the buffer and update the agent's network.
experience, unused_info = next(iterator)
train_loss = agent.train(experience).loss step = agent.train_step_counter.numpy() # Print loss every 200 steps.
if step % 200 == 0:
print('step = {0}: loss = {1}'.format(step, train_loss)) # Evaluate agent's performance every 1000 steps.
if step % 1000 == 0:
avg_return = compute_avg_return(env, agent.policy, 5)
print('step = {0}: Average Return = {1}'.format(step, avg_return))
returns.append(avg_return)
情节
我们现在可以画出当我们训练代理人时,累积的平均回报是如何变化的。为此,我们将使用 matplotlib 制作一个非常简单的绘图。
iterations = range(0, num_iterations + 1, 1000)
plt.plot(iterations, returns)
plt.ylabel('Average Return')
plt.xlabel('Iterations')
《DQN 特工》5 集的平均回报率。随着代理变得更有经验,您可以看到性能是如何随着时间的推移而提高的。
完全码
我已经把本文中的所有代码作为 Google Colab 笔记本进行了分享。你可以直接运行所有代码,如果你想改变它,你必须把它保存在你自己的 Google drive 账户上,然后你可以做任何你想做的事情。如果你愿意,你也可以下载它在你的本地计算机上运行。
从这里去哪里
- 你可以跟随 Github 上 TF-Agents 库中的教程
- 如果你想查看 RL 的其他好框架,你可以在这里看到我以前的帖子:
从头开始编程你自己的强化学习实现可能会有很多工作,但是你不需要做…
towardsdatascience.com](/5-frameworks-for-reinforcement-learning-on-python-1447fede2f18)
- 你也可以在我前段时间写的另一篇文章的中查看其他可以尝试 TF-Agents(或者任何你选择的 RL 算法)的环境。
老规矩,感谢阅读!请在回复中告诉我你对 TF-Agents 的看法,如果你有任何问题或发现任何问题,也请告诉我🐛在代码中。
重塑办公室之外的工作场所
如何在家中舒适地高效工作
佩吉·科迪在 Unsplash 上拍摄的照片
在过去的几十年里,技术承诺将我们从工作场所中解放出来,并使我们能够在任何地方工作。然而,这从未成为现实,因为企业不愿放松对员工的控制。然而,疫情的崛起让雇主别无选择。这立即成为一个生死存亡的问题,不适应的公司面临倒闭的风险。
幸运的是,我们生活在一个科技发达的世界,将工作转移到网上相当容易。第一个也是最明显的要求是良好的互联网连接,因为这将成为我们所有数字服务的网关。考虑到西方国家平均有 85%的家庭宽带普及率,这一要求在西方国家不成问题。在其他国家,有各种技术提供了替代方案,如通过手机访问互联网,或通过谷歌的 Loon 气球动力互联网获得直播链接,为偏远地区提供服务。第二个基本要求是能够连接互联网的数字设备,如笔记本电脑或平板电脑。
一旦满足了这两个要求,现在就该转向必要的应用程序了。这些应用程序大多数都是免费的,可以通过浏览器访问,所以它们倾向于独立于硬件。一个人所要做的就是去他们的网站并使用该应用程序。以下是需要开始使用的应用程序列表。
- 一个在线日历对于安排和组织会议是必不可少的。它可以从位于任何地方的任何设备访问。
- 与同事或客户的快速聊天可以通过电子邮件或各种消息应用程序进行,如 WhatsApp、Messenger、Slack 和无数其他应用程序。
- 对于更长时间的会议,人们可能需要一个视频会议应用程序,如 Skype 或 Zoom。其中大多数是免费的,允许多人在一个虚拟的房间里会面。
- 为了执行复杂的项目,像 Trello 这样的应用程序通过将任务细分为子任务并分配给不同的团队成员来帮助人们管理任务。分配给特定任务的最后期限会让人们受到约束。
- 与不同地点和时区的人一起工作可能会很棘手。正因为如此,像谷歌的 G Suite 和微软的 Office 365 这样的工具帮助团队成员同时协作处理各种文档。这些套件支持最流行的生产力应用程序,如 Word、Excel、Powerpoint 或它们的变体(100%兼容)。他们还为用户提供云存储,从而确保文件安全地保存在远程位置。
- 在当今快速发展的世界中,跟上新的概念是非常重要的。像 Coursera、Udemy 和 edX 这样的网站提供免费在线课程,其中一些课程得到了顶尖大学的认证。他们允许员工在自己舒适的家里用自己的时间学习,从而让他们有更好的职业前景。
- 最后,由于在家里可能仍然需要访问办公室电脑,Chrome 远程桌面帮助用户从任何设备安全地访问他们的机器。
有了所有这些应用程序,您马上就可以开始工作了。经过几次尝试后,人们开始意识到,远程工作最终与在办公室工作没有太大区别。人们仍然可以组织一对一会议、小组会议、共享文档或寻求建议。
杰佛逊·桑托斯在 Unsplash 上的照片
然而,远程工作也带来了以下一些缺陷:
- 办公时间有了全新的含义。人们可以在白天和晚上的任何时间工作,因为办公室现在只有一米远。过度的自由当然是不健康的,因为人们下班后需要拔掉电源。因此,设定时间限制是至关重要的,这样可以避免过度工作并最终耗尽精力。
- 在家工作可能会感到孤独和无聊,因为在网上组织办公室笑话很有挑战性。尽管这些东西不会直接提高组织的生产率,但它们有助于员工团结、建立信任,并更好地合作。因此,通过聊天或虚拟活动保持一个开放的渠道是至关重要的,在虚拟活动中,员工可以分享有趣的东西,如他们的生活片段、模因、有趣的视频或其他社交内容。
- 中介沟通不一定是自然而然的。许多人在视频会议期间感到不舒服,因为它往往会淡化人与人之间的互动暗示。人们说话时通常会看着某人的眼睛,但在视频会议中不会发生这种情况,因为他们正在看着摄像机。其他人也倾向于打手势,但这在视频通话中减少了几次。所以有时候,视频通话对人们来说很尴尬,在这种情况下,如果让他们感到不舒服,人们应该可以选择关闭相机。
- 呆在办公室里也带来了偶然的交流,人们可以通过这种交流非正式地了解一个项目的更多细节。这种形式的交流通常发生在走廊或休息时间。尽管许多组织试图阻止这种情况,转而支持更结构化的沟通渠道,但事实是这种情况仍然存在,并有助于员工理解不同的观点。当然,在家工作时不会发生这种情况,员工可能不了解特定情况的整个背景。在这种情况下,公司应该推行透明的议程,让所有团队成员在有组织的聊天中分享关于特定项目的一切。
- 起床上班,从床上滚下来,发现自己在家庭办公室里,这是不健康的。早晨的习惯对于保持某种正常感是必不可少的(特别是当远程工作是一种强加而不是一种选择的时候)。最好的事情是从事一些身体活动,花时间冥想,吃一顿健康的早餐,打扮一下,开始工作。当然,每个人都有自己理想的完美早间作息模式,保持这种模式对保持动力至关重要。
- 最后,我们不要忘记家是所有干扰的中心。毛毛猫可能会在键盘上跳来跳去以引起注意,孩子们开始从另一个房间大喊大叫,大脑思考着神话般的网飞系列的结局,餐具室每 5 分钟就叫你拿一份点心。这么多事情可以浪费你的时间!不幸的是,分心在每个环境中都是现实;我们必须接受它们,学会与它们共处,并尽可能设定界限。
布鲁克·拉克在 Unsplash 拍摄的照片
但是即使在家工作有它的挑战,它也能提供各种各样的好处;
- 通勤变得不存在,从而节省了人们的旅行时间,交通相关的挫折和汽车费用。想想看,一个人每天多花一个小时,省下几百欧元,能做些什么!
- 每人每年可以减少至少 2.3 公吨二氧化碳的碳足迹。
- 在家也意味着一个人可以完全控制自己的饮食。因为同伴压力而做出的不健康选择将成为过去——再也没有借口吃快餐了,因为厨房里没有微波炉。选择完全取决于个人!
- 公司根据他们的品牌方针设计他们的办公室,同时优先考虑功能性和互动性。但是家庭办公室是不同的;它反映了员工的个人主义风格。这个人是一个风水怪胎,喜欢在北极的温度下工作,但被热带植物包围,还是一个被锁在黑暗房间里的地下地下城主,这完全取决于个人。这些选择使家庭办公室成为一个有趣的空间,帮助员工提高生产力。
- 最后,远程工作不一定要在家里进行。如果没有健康限制(就像疫情实施的那样),员工可以在咖啡店、共同工作空间甚至大自然中舒适地工作。如果想更进一步,他也可以在一个或几个国家工作。这些人通常被称为数字游牧者,因为他们使用技术谋生,同时过着游牧生活。
艾玛·马修斯数字内容制作在 Unsplash 拍摄的照片
本文试图描绘一幅远程工作的真实画面。该系统远非完美,但它确实提供了各种优势,足以满足现代工作场所的需求。有一点是肯定的,当健康紧急情况消退时,我们不能回到我们的旧习惯,但我们必须进一步投资,改善远程工作实践。我们永远不知道下一次疫情什么时候会袭击我们,它可能比我们想象的要快。当它到来时,我们必须做好准备。从现在开始,远程办公不应该成为我们在需要时公开的秘密武器,而是我们当前工作实践的延伸。在家工作应该是我们的第二天性。只有这样,当下一次疫情袭击我们时,我们才能不受干扰地继续工作。
本文原载于【会计师】。请在下面留下你的想法评论。如果你喜欢这篇文章,请跟我来🐦推特,🔗 LinkedIn ,📷 Instagram 或者😊脸书
正如我们所知,人工智能正在如何改变汽车保险
towardsdatascience.com](/killing-the-motor-underwriter-cb11317cda98) [## 依靠人工智能
利用人工智能在新的十年里重塑银行业
towardsdatascience.com](/banking-on-ai-27d4d39bda1c) [## 在 2020 年推动您的小型企业
毫无疑问,2019 年是人工智能(AI)年。我们听说了很多,但很多人不确定…
towardsdatascience.com](/boosting-your-small-business-in-2020-6ae3529cbfb0)
Alexei DingliProf 是马耳他大学的 AI 教授。二十多年来,他一直在人工智能领域进行研究和工作,协助不同的公司实施人工智能解决方案。他的工作被国际专家评为世界级,并赢得了几个当地和国际奖项(如欧洲航天局、世界知识产权组织和联合国等)。他出版了几本同行评审的出版物,并且是马耳他的一员。由马耳他政府成立的人工智能工作组,旨在使马耳他成为世界上人工智能水平最高的国家之一。*
使用 SciPy 层次聚类重塑传统篮球位置
使用 python 中的等级聚类分析查看五个位置的函数如何随时间变化
波士顿凯尔特人队教练布拉德·史蒂文斯说:“我再也没有这五个位置了。”。“现在可能只有三个位置,你要么是控球者,要么是边锋,要么是大个子。”在过去的 10 年里,我们已经看到了大前锋和中锋的功能的演变,从被期望去低位完成利用他们的身高和力量得分,他们被期望去伸展地板和击倒三分。我想调查截至 2018-19 赛季的位置变化。
雪莉·胡利
调查指南
我要做的第一件事是收集 NBA 所有现役球员的赛季平均数据。我用的代码如图 本文 **。**这给了我关于 这一页 关于basketball-reference.com的所有统计数据。
图片来自 Basketball-Reference.com
我将对这些数据进行的操作称为层次聚类。也被称为分层聚类分析,这是一种根据相似的统计数据对对象(在这种情况下是球员)进行聚类的算法。我使用了一个名为 SciPy 的模块来做这件事。我用的参数是 FG,FGA,FG%,3P,3PA,3P%,2P,2PA,2P%,eFG%,FT,FTA,FT%,ORB,DRB,TRB,AST,STL,BLK,TOV,PF,PTS。所有其他的数据都与调查无关,但是我确实使用了比赛次数,每场比赛的时间以及分数来过滤掉低价值的球员。我剔除了所有场均得分低于 10 分、每场比赛上场时间低于 20 分钟的球员(这大约是一场比赛的 42%),以及那些在赛季中出场少于 50 场的球员(这是可用比赛的 61%)。
进行调查
我要做的第一件事就是收集数据。这是比较容易的部分,因为我只是使用了前面文章中的代码。返回熊猫数据框中的统计数据。这样做的第一个问题是,球员的数据是以字符串的形式存储的,而我需要它们以浮点数的形式存储,所以我在将它们放入数据框之前对它们进行了更改,它们是一个二维数组。
forbidden =[0,1,3]
for x in player_stats:
i=0
while i<len(x):
if i in forbidden or x[i] == **''**:
pass
else:
x[i] = float(x[i])
i+=1
“禁止”是数据框中字符串的索引(姓名、位置和球队),而“球员统计”是二维数组。
然后我需要过滤掉统计数据。一些球员丢失了数据,例如科斯塔斯·安特托昆波斯·3P %丢失了,所以我不得不删除所有数据为空的球员。这只发生在百分比上。
来自 basketball-reference.com
stats = pd.DataFrame(player_stats, columns = headers)
stats.head(10)
data = stats.drop(columns=**"Pos"**)
data = data.drop(columns=**"Tm"**)
nan_value = float(**"NaN"**)
data.replace(**""**, nan_value, inplace=True)
data.dropna(subset = [**"2P%"**], inplace=True)
data.dropna(subset = [**"FT%"**], inplace=True)
data.dropna(subset = [**"3P%"**], inplace=True)
data.dropna(subset = [**"FG%"**], inplace=True)
data.dropna(subset = [**"eFG%"**], inplace=True)
data = data.dropna()
这将创建数据框,移除职位和团队(与调查无关)并用“NaN”(一个常见的占位符)替换任何空值,然后从数据框中删除具有此占位符的任何行。然后,我需要删除不符合我之前指定的标准的行。
data = data[data[**'G'**] > 50]
data = data[data[**'PTS'**] > 10]
data = data[data[**'MP'**] > 10]
然后我需要做最后的准备。我需要删除球员的名字,游戏和游戏开始了。所有这三个字段对调查来说都是不必要的,所以我只是将它们放入一个新的数据框中,因为我想保留 树状图 (输出的图形)的名称。
ds = data.drop(columns =**"Player"**)
ds = ds.drop(columns =**'G'**)
ds = ds.drop(columns = **'GS'**)
然后,我需要获得一个 NumPy N 维数组 中的名字,因为这是树状图标签需要传递到层次聚类函数中的格式。
namesarray = data[**'Player'**].to_numpy()
最后,我必须设置绘图大小和分辨率,给树状图一个标题,然后剩下要做的就是将这些参数传递给 SciPy 层次聚类函数,然后显示树状图
plt.figure(figsize=(10, 7), dpi = 300)
plt.title(**"Redefining positions"**)
dend = shc.dendrogram(shc.linkage(ds, method=**'ward'**), labels=namesarray)
plt.show()
得出的结论
从生成的树状图中,我设法推断出 5 个不同的位置。请记住,这些结果来自 2018-19 NBA 赛季,并不反映球员的整个职业生涯。
传统大人物
哈桑·怀特塞德和鲁迪·戈贝尔分别代表波特兰开拓者队和犹他爵士队。史蒂夫·米切尔-今日美国体育
传统的大男人是一个濒临灭绝的品种。他们被期望更多的伸展地板,而不是背对篮筐。他们的篮板和篮筐保护令人惊叹,但他们在现代比赛中投篮能力的缺乏限制了他们的得分量。这些球员有很高的 FG%但是低到没有 3PA。这些参与者包括:
- 鲁迪·戈贝尔
- 哈桑·怀特塞德
- 贾维尔·麦基
双向全方位威胁
勒布朗詹姆斯和科怀·伦纳德分别为洛杉矶湖人队和洛杉矶快船。林浩伟/美联社
这些玩家在游戏的几乎所有领域都表现出色。篮板,抢断,得分,助攻,同时也有一个很好的(不是很好的)3 分投篮。这些类型的球员通常都是联盟中的佼佼者。这些参与者包括:
- 科怀·伦纳德
- 勒布朗·詹姆斯
- 乔尔·恩比德
持球者
朱·霍勒迪和凯里·欧文分别代表新奥尔良鹈鹕队和布鲁克林篮网队。图片来自美联社图片/Mary altafer
控球手是…嗯,控球手。他们的得分量可以有很大的不同,但有一点是他们都有很高的助攻数。尽管没有在本次调查中进行测量,但它们的使用率都很高。这些参与者包括:
- 朱·霍勒迪
- 凯里·欧文
- 卢卡·东契奇
伸展四肢(和四肢)
多伦多猛龙队的帕斯卡尔·西亚卡姆。卡洛斯·奥索里奥/美联社
伸展四人组是拥有 3 分投篮的大前锋。他们可以有效地冲向篮筐,但在接球投篮 3 种情况下也很有效。他们通常也有很高的篮板数和很低的助攻数,但也有例外。其中包括的一些玩家是:
- 杰森·塔图姆
- 帕斯卡尔·西亚卡姆
- 卡尔-安东尼·唐斯
三点专家
詹姆斯·哈登和克莱·汤普森分别代表休斯顿火箭队和金州勇士队。特洛伊·陶尔米纳/今日美国
虽然这些球员可能不仅仅局限于三分球,但他们确实有尝试很多三分球的天赋,而且成功率很高。这些球员都是出色的得分手,他们既可以创造自己的投篮机会,也可以用接球投篮得分。这些参与者包括:
- 克莱·汤普森
- 詹姆斯·哈登
- 布拉德利·比尔
结束语
首先,我想说调查结果是 而不是 100%正确,你不应该相信我的话。从这些数据中你只能推断出这么多。使用率、拍摄地点以及游戏风格等其他因素都没有考虑在内。虽然有很大的改进空间,但在我看来,这是有一定道理的。不过,随你怎么想吧。所有的代码和最终的树状图都在这里链接的一个 GitHub 库中。
关系和机器学习:它们有什么共同点?
【剧透预警】答案过拟合
照片由 Geran de Klerk 在 Unsplash 上拍摄
我一直认为过度适应相当于一对已经在一起很长时间的夫妇的机器学习。
也许用这种说法来开始一篇文章有点过了,所以如果这听起来很奇怪,检查一下图片中的几只斑马。让我们称他们为迪克和简,并假设他们已经在一起一段时间了。事实上,时间太长了,以至于他们对另一只斑马了如指掌,甚至知道它如何说话、思考,甚至在打斗即将爆发前会发生什么(顺便说一句,这是自我保护的关键信息)。因此,迪克和简感到舒适,并开始认为这种关系/情侣的事情很容易,他们已经成为“阅读”面部斑马表情的艺术专家,用斑马语言解释单词,甚至肢体语言,如尾巴摆动;它们知道另一只斑马什么时候高兴、悲伤或生气,甚至知道该说什么或做什么来达到自己的目的。迪克和简是关系游戏的大师,对吗?
不对。证据呢。在一起多年后,他们分手了,是时候再次回到约会游戏中了(对你们中的一些人来说,约会是一件如此严肃的事情,几乎不能称之为“游戏”)。但是我们的小斑马朋友发现这其实很难。也许他们并不像自己想象的那样擅长约会/恋爱。你猜怎么着?他们可能不是(你也不是)。那么,为什么迪克和简曾经认为他们是关系的主人呢?
因为他们正在做一些好的旧的过度配合(关系风格)!是的,他们建立了一个基于单一斑马的关系学习模型,并认为它适用于所有斑马。举例来说,迪克认为因为他的小把戏对简起了作用,它们也会对他未来的夫妇起作用,但后来他发现不同的斑马实际上是互不相同的。惊讶吗?欢迎来到过度合身的危险世界。
机器学习中的过拟合
所以,动物王国到此为止。过度拟合通常发生在监督学习中,当您仅基于实例的特定样本构建模型时。基本上,您的模型“记忆”样本中个体的目标变量的属性和值,然后,当您要求对同一样本中的一个个体进行预测时,模型会简单地吐出之前记忆的该个体的目标变量的值,并将其称为“预测”。听起来很熟悉?这是应该的,因为这正是 Excel 的 VLOOKUP 公式所做的:您给它输入一个值,它在表上查找该值所在的行,然后返回同一行的另一列的值。我想我们都同意 VLOOKUP 公式不是一个机器学习模型,即使在它最疯狂的梦想中也不是。
这就好比你对你的浪漫伴侣太了解了,你知道当他/她扬起左眉的时候,一场争斗就要开始了。嗯,这对这个特定的人来说很好,但也许当你有了新的伴侣,你会发现,对这个新人来说,扬眉实际上是一种**“让我们浪漫起来”**(如果你知道我的意思)的标志。
虽然这听起来很傻,但这是数据科学中常见的错误。你建立了一个模型并爱上了它,因为它完美地预测了你的训练集的每一个实例。你把它推销给你的老板,组织一个团队会议来展示你的大想法,在问答环节的 30 秒内,你的 it 经验丰富的同事否决了它,因为它似乎不能很好地推广到其他情况。所以现在你只是在大家面前看起来像个傻瓜…
非常严重的是,公司有时会花费数百万美元来建立简单记忆数据集的模型,并称之为“预测模型”。基本上,你只是花了一堆钱做了一些你本可以在 30 秒左右完成的事情(还记得那个 VLOOKUP 公式吗?)
那么,我们如何避免过度拟合的危险呢?
很高兴你问了。这里有三个总的想法要记住,而发动战争过度拟合。
训练/测试集拆分
这是经典的。我不打算深究,因为它已经在教科书和 YouTube 视频中被远比我更有趣、更感同身受的人解释过无数次了。让我告诉你这个想法:如果你是一个三年级的数学老师,你不会用你给学生的练习作为实际测试的练习。为什么不呢?嗯,因为仅仅记住练习页后面的答案并在考试中重复它们太容易了,所以几乎没有数学学习在进行。如果你明白这一点,你就明白了训练/测试拆分在机器学习模型构建中的重要性。这里的教训很简单:永远不要用你用来构建模型的相同数据来测试模型,否则它会欺骗你,就像你的学生一样。
交叉验证
比方说,你喜欢烹饪,你想出了一个全新的食谱来制作一个世界上从未尝过的美味香蕉面包。你想找到一种方法来客观地确定你的食谱是否好,或者只是你神奇的烹饪技巧使它尝起来很棒(我会称之为烹饪过度)。所以你召集了十个想一起去的烹饪专家。你把食谱给他们中的八个人,他们准备面包,然后让剩下的两个人试一试,并从 1 到 10 打分。你和同样的十位专家重复这个实验,但是这次你让不同的一对夫妇来尝试并评分。你再这样做三次,你的香蕉面包就有了五个不同的等级,每个等级都来自不同的烹饪专家。为了得到你的食谱有多好的最终等级,你平均五个等级,你就完成了。
简单来说,这就是交叉验证。为了了解机器学习模型到底有多好,您将数据分成训练集和测试集几次,始终保持相同的比例(在本例中为 80/20 ),但旋转测试准确性的实例。在十个实例的数据集中,它看起来是这样的:
作者图片
在左边,完整的数据集(每根香蕉都是一个实例);在右侧,同一个数据集,只是现在我们已经执行了五个不同的训练/测试分割,称为折叠:对于每个分割,黄色香蕉是用于构建模型的实例,绿色香蕉代表我们将用于测试它的实例。这就是“x-fold 交叉验证”这个名字的由来。在这种情况下,这是一个 5 重交叉验证,因为我们有 5 个不同的分裂,但 10 重交叉验证也很常见。
现在,剩下要做的就是在每个不同的折叠上测试模型的准确性,计算一些总体准确性的总度量,我们就完成了。这个总得分应该为我们提供模型预测目标变量能力的可靠量化,并且它还应该为我们提供过度拟合可能性的良好提示。请记住:总是要找到客观的方法来衡量你的模特的表现和过度拟合的倾向。
复杂性控制
作者图片
是的,那就是我,试图成为一个写歌英雄,顺便说一句,这从来没有发生过。伙计,那东西太难了。你知道当你写一首歌,但它是如此的无聊和简单,以至于没有人有兴趣听它?所以你试图让它变得更复杂和有趣,人们开始喜欢它,所以你让它变得更复杂,但每个人仍然喜欢它。然后你开始想“伙计,我是个不错的歌曲作者。歌曲越复杂,效果就越好”。
只是实际上并不是这样。当你的歌曲过于复杂,只能吸引音乐专家时,你就会失去大部分听众(倒 U 型曲线的一个很好的例子)。我的朋友,这个叫做复杂性控制,它也适用于机器学习模型。
基本上,过于简单的机器学习模型不会很好地捕捉数据中的模式。因此,它会对你的目标变量做出非常模糊的预测,精确度可能非常低。就像你对你的歌所做的那样,你可能会增加它的复杂性(也许是通过增加更多的解释变量,例如在线性回归的情况下)以使预测更加准确。然而,就像你的歌一样,这只会在一定程度上起作用,之后…不出所料,你的模型开始过度拟合训练数据,其性能水平下降。所以,简而言之,不要太纠结于复杂性,否则它会让你所有的粉丝远离你,回到布鲁诺·马斯的那首歌(反正肯定比你的好)。
这些只是许多想法中的一些非常普遍的想法。这里的要点是让你对过度拟合的危险有一个全面的认识,并找到一些线索去寻找解决方案。对于那些有兴趣深入了解的人来说,YouTube 上有很多很棒的频道,有着令人惊叹的相关内容。你会在这里找到几个和这里的。
斑马,重访
还记得我们的朋友迪克和简吗?我想告诉你他们复合了,但事实是他们没有。事实上,他们做了一些更好的事情:他们每个人都开发了更聪明的关系学习模型,广泛适用于更多的斑马,并使它们不仅能够找到新的伴侣,还能显著增加非洲大草原上斑马的数量。我想我们都是赢家,不是吗?
相对重要性分析:交流多元回归结果的更好方法
任何行业客户都关心推动结果(Y)的因素(X 变量)的相对重要性。员工流动的最强预测因素是什么?哪些客户最有可能给我们带来回头客?服务体验的哪些方面与客户满意度联系最紧密?
回答这些问题的传统方法是回归分析。然而,没有统计背景,很难解释这种分析的结果。很难解释其中一个预测因子的单位变化与 y 的比例变化相关联。系数可能有时会产生关于 X 变量重要性的误导性结果。
另一种方法是将这种分析的结果解释为百分比,代表每个预测因子的相对重要性。这是一种更直接的方式来传达这样的发现。
已经有几种计算相对重要性的方法被提出来了(关于综述,请参见 Johnson & LeBreton,2004 和 Tonidandel & LeBreton,2011 ),但是我将概述一种相对简单的方法。这种方法的优点是它可以很容易地从回归和协方差表的结果中计算出来,并且不需要任何进一步的计算。此外,它直接对应于多重 R-Square,并考虑了预测因子的共线性。它也不受任何预测因子的重新标度的影响。
一个例子
为了说明这种方法,假设您受一家餐馆老板的委托来确定客户满意度的最重要驱动因素,并且您在 500 名客户中进行了一项调查来回答这个问题。
你确定的三个潜在因素包括对以下方面的满意度:(1)物有所值,(2)食物质量,(3)客户服务。让我们假设物有所值是用 1(物有所值极差)到 10(物有所值极好)的尺度来衡量的,但另外两个是用 1(非常不满意)到 5(非常满意)的尺度来衡量的。
结果变量是一个净促进者分数。(在 0 到 10 分的范围内,您向朋友或同事推荐这家餐厅的可能性有多大?)
生成该数据集的 R 代码如下所示:
load.package <- function(x)
{
if (!require(x,character.only = TRUE))
{
install.packages(x,dep=TRUE)
if(!require(x,character.only = TRUE)) stop("Package not found")
}
}# Load the MASS package
load.package("MASS")# Generate a dataset using MASS----
dimnames <- c("Value for money", "Quality of food", "Customer service", "Net Promoter")
covMat <- matrix(data = c(1,-0.2, 0.01, 0.4,
-0.2, 1, 0.10, 0.4,
0.01, 0.10, 1, 0.5,
0.4, 0.4, 0.5, 1), nrow = 4, ncol = 4, dimnames = list(dimnames, dimnames))
dataset.standardized <- mvrnorm(n = 500, mu = c(0,0,0,0), Sigma = covMat, empirical = TRUE)# Rescale the variables----
dataset <- dataset.standardized
for (a in 1:dim(dataset.standardized)[2]) {
dataset_min <- min(dataset[,a])
dataset[,a] <- dataset.standardized[,a] - dataset_min
dataset_max <- max(dataset[,a])
dataset[,a] <- dataset[,a] / dataset_max
}
dataset[,1] <- dataset[,1] * 9 + 1
dataset[,2] <- dataset[,2] * 4 + 1
dataset[,3] <- dataset[,3] * 4 + 1
dataset[,4] <- dataset[,4] * 10# Convert each matrix to a data frame
dataset.standardized <- as.data.frame(dataset.standardized)
dataset <- as.data.frame(dataset)
已经创建了两个数据集:一个数据集的变量是原始度量,另一个(标准化)数据集的每个变量都经过了重新调整,方差为 1。
描述性统计(平均值、标准偏差和变量间的相关性)如下所示:
表 1。描述统计学
回归分析的代码如下所示。我提出了非标准化和标准化(β)系数(并省略了标准误差、 t 统计和 p 值):
# Fit regression model----
regmodel <- lm(`Net Promoter` ~ `Value for money` + `Quality of food` + `Customer service`, data=dataset)
regmodel.std <- lm(`Net Promoter` ~ `Value for money` + `Quality of food` + `Customer service`, data=dataset.standardized)coefs <- data.frame("Unstandardized" = regmodel$coefficients[2:4],
"Beta" = regmodel.std$coefficients[2:4])coefs
回归的结果是:
表二。回归结果
估计相对重要性的一个简单而相当常用的方法是将每个回归系数表示为系数总和的百分比。对于非标准化系数和贝塔系数,我在下面介绍了这种方法:
# Relative importance: traditional method----
coefs$`RI Traditional` <- coefs$Unstandardized / sum(coefs$Unstandardized)
coefs$`RI Traditional (std)` <- coefs$Beta / sum(coefs$Beta)
coefs
表 3。相对重要性的传统衡量标准
查看结果,我们可以立即发现一些问题。首先,非标准化和标准化的解决方案给出了截然不同的结果。换句话说,该方法不考虑变量的缩放方式。
第二个(不太明显的)问题是,该方法没有考虑每个 X 变量之间的相关性。尽管在此分析中不存在问题,但也不清楚如何处理负回归系数,尤其是那些由预测值的高度共线性引起的系数。(实际上,一些研究人员会将此类变量报告为 0%,但这歪曲了他们的贡献。)
另一种(基于模型的)方法
用每个 X 变量在 Y 变量中所占的方差比例来表示相对重要性会更好。在回归分析中,这就是 R 平方统计向我们展示的。但是怎么才能把 R-Square 分解成各个预测器解释的比例呢?
首先,解释一下 R 平方是如何计算的是很有用的。r 平方由以下公式给出:
其中 X 代表每个预测值, Y 代表结果变量, j 是模型中 X 个变量的个数, B 是每个回归系数,SD 代表每个变量的标准差。如果变量是标准化的,我们可以简单地用 1 代替每个 SD。
将此公式应用于我们的示例,R 平方等于:
分子代表每个 X 变量的方差。扩展分子得到以下等式:
其中 Var 代表每个变量的方差(标准差的平方),Cov 代表两个变量之间的协方差(两个变量的联合可变性)。如果这两个变量是标准化的,协方差就相当于一个相关性。
这个方程划分了 X 变量的方差,指出了哪些预测因子是最重要的。
前三项——0.413 Var(X1)、0.919 Var(X2)和 1.206 Var(X3)是明确的,因为它们是与 Y 变量直接相关的方差。然而,等式第二行的协方差项更难解释,因为它们代表共同的可变性。我们应该将这个共享方差分配给哪个变量?
从我们的例子中,让我们检查 X2(食品质量)和 X3(客户服务)。这些变量的协方差为 0.038(相关性为 0.100)。如果我们将每个预测值和共享区域所占的方差可视化,它看起来会是这样的:
红色区域代表食物质量的差异;蓝色区域代表由客户服务计算的差异。中间的紫色区域代表不能分摊给 X2 或 X3 的共同差异。在某些方面,这就像是国家之间的领土争端。
如何划分(并征服)共享区域
我的建议是,根据每个变量直接解释的方差大小,按比例划分共享方差。
因此,对于食品质量和客户服务,分配给双方的共享差异为:
在这种情况下,因为变量之间的相关性很小,所以两个变量所占的共享可变性也很小。因此,没有太多可以分割的。然而,对于高度相关的变量,这个区域要大得多。
该解决方案具有几个吸引人的特征:它考虑了每个变量的范围,它考虑了每个变量和结果之间的关系的强度,它不产生越界结果(例如,负方差解释),它可以适应负系数,它可以使用分析的输出直接计算,并且它考虑了预测值之间的相关性。
在 R 中,实现这种方法的语法如下:
# First, we create a matrix depicting the variance accounted for by each variable. The diagonal shows the variance directly attributable to each variable. The off-diagonal shows the shared variance attributable to both variables.var.exp <- matrix(data = NA, nrow = dim(coefs)[1], ncol = dim(coefs)[1])
for (y in 1:dim(coefs)[1]) {
for (x in 1:dim(coefs)[1]) {
var.exp[y,x] = cov(dataset)[y,x] * coefs$Unstandardized[y] * coefs$Unstandardized[x]
}
}coefs$`Var accounted for` <- 0
for (y in 1:dim(coefs)[1]) {
for (x in 1:dim(coefs)[1]) {
if (x == y) {
coefs$`Var accounted for`[y] = coefs$`Var accounted for`[y] + var.exp[y,y]
}
else {
coefs$`Var accounted for`[y] = coefs$`Var accounted for`[y] + var.exp[y,x] * (var.exp[y,y] / (var.exp[y,y] + var.exp[x,x]))
coefs$`Var accounted for`[x] = coefs$`Var accounted for`[x] + var.exp[y,x] * (var.exp[x,x] / (var.exp[y,y] + var.exp[x,x]))
}
}
}coefs$`RI (new method)` <- coefs$`Var accounted for` / sum(coefs$`Var accounted for`)coefs
这种方法的结果如下所示:
表 3:相对重要性的新衡量标准(最后一栏)
相对重要性的新度量产生了与以前的方法相当不同的结果。尽管 beta 系数最大,但就相对重要性而言,性价比被认为是最低的。这个结果有一个有趣的原因,它与 X 变量之间的相关性有关。
X 变量之间的相关性如何影响相对重要性?
这种方法似乎意味着高度相关的变量比不相关的变量更重要。相反,负相关的变量就不那么重要了。为什么会这样呢?
对预测因子之间正相关的一种解释是相互因果关系。例如,如果餐馆老板通过更多的员工培训来改善顾客服务,它也可以提高食物的质量(如果厨师的技能和能力提高的话)。或者,改善食物可能会导致顾客忽略糟糕的顾客服务。每个预测因素都更重要,因为改善其中一个因素会对另一个因素产生积极的影响。
相反,变量之间的负相关往往代表某种情境约束。在我们的例子中,如果餐馆老板决定提高他们饭菜的质量,很可能需要提高价格。同样,如果餐馆老板决定降低价格,这可能意味着在其他方面节省成本,例如使用低质量的原料。因此,每个预测因子都不那么重要,因为提高一个会以牺牲另一个为代价。换句话说,共享方差是从直接归因于其他变量的方差中减去。
一些事后的想法和警告
你可能会想:当谈到共享方差时,为什么不简单地在每个变量之间对半分呢?这似乎是一个吸引人的解决方案,但它会引起一些问题。特别是,如果两个变量负相关,并且由一个变量解释的方差非常低,那么它会导致负方差。
从因果关系的角度来看,推荐的解决方案假设 X 变量之间的相关性代表相互影响。事实上,X 变量之间存在关联还有其他可能性。X 变量中的一个可能是第二个的原因。可能有第三个(省略)变量负责相关。这些不同的情景可能会对每个变量的相对重要性产生影响。
参考
j . w . Johnson 和 j . m . LeBreton(2004 年)。组织研究中相对重要性指数的历史和使用。组织研究方法,7(3),238–257。土井: 10.1177/1094428104266510
s .托尼丹德尔和 J. M .勒布雷顿(2011 年)。相对重要性分析:回归分析的有益补充。商业和心理学杂志,26(1),1-9。doi:10.1007/s 10869–010–9204–3
LVQ 的相关更新
学习矢量量化是一种简单而强大的分类算法。使用训练数据,该算法试图使原型适合每个类,使得每个原型最佳地代表它们各自的类。为了符合原型,必须使用一些相似性度量。最常见的是使用简单的老式欧几里德距离:
对于训练过程,为每个类初始化原型。每个类可以配置多个原型。然后,训练算法会尝试移动这些原型,使它们最好地代表它们各自的类。对于训练集中的每个数据点,训练算法使用给定的距离度量找到最接近的原型,如果类别标签不同,则推开该原型,如果类别标签匹配,则吸引该原型。它对训练数据集中的每个点都这样做,如果需要的话,多次扫过整个数据集以达到收敛。下面的动画演示了简单数据集的训练过程。类别 1 由 2 个原型(大圆圈)表示,因为它被分成两个集群。收敛后,通过计算新数据点到所有原型的距离并选择最近的原型的类别来进行新的预测。
然而,有一个问题:欧几里德距离度量对每个输入维度进行同等加权,这通常是不期望的。要素的缩放比例可能不同,或者一个要素可能非常嘈杂。这些特征提供很少的辨别能力,但是对计算的距离有同等的贡献。举个例子:假设我们正在尝试构建一个分类器,根据一个人头发的长度和一个人的身高来区分男人和女人。然而,我们正在处理一个数据集,其中每个人的头发长度都相似。在这种情况下,头发长度并不是一个非常有用的区分男女的特征。当然,我们可以使用基本的统计分析自己得出这个结论,但通常情况下,这些事情非常微妙。如果有什么能帮我们解决这个问题,那不是很好吗?原来是有的!我们可以改变欧几里德距离度量,使得每个输入维度根据某个因子进行加权:
加权欧几里德距离
向量λ也被称为相关性向量。它通过一些因素来衡量每一个输入,这样,如果我们正确地选择λ的值,它将帮助我们摆脱歧视性较小的维度。
然而,这并没有解决问题:我们如何量化每个特征的区分能力?好消息是我们根本不需要做任何特别的事情!我们所要做的就是调整算法,让它自己更新相关向量。是不是很棒!?然后在训练之后,相关向量λ代表每个特征的重要性。不太重要的特征对距离度量的权重降低,而具有良好辨别能力的特征被提供高值。
因为相关性(λ)向量在算法过程中改变,所以上述距离度量也可以被称为自适应距离度量。负责这一切的算法被称为相关性学习矢量量化(RLVQ)。
太酷了!我们如何做到这一点?
RLVQ 算法实际上非常类似于常规 LVQ,我们只需要用相关向量更新规则来扩充它。根据以下规则,关联向量与原型一起被更新:
如果当前特征向量与最近的原型具有相同的类别(下标 i 代表每个向量中的第 i- 个元素)。
如果当前特征向量与最近的原型不具有相同的类别。
上述更新规则适用于相关性向量λ中的所有元素 i 。 α 表示相关性学习率。在每次更新相关性向量之后,它必须被归一化,使得它的元素之和为 1。此外,相关性向量的任何元素都不允许为负。如果相关性向量的任何分量在训练期间变成负的,则它必须被设置为零。另一方面:相关性向量不必是全局的。您可以为每个原型或每个类使用不同的相关性向量。原型和 lambda 向量同时更新。
这些更新规则可能看起来有些随意,但是可以被激励如下:如果特征向量被错误地分类,那么如果特征向量的第 l 个分量接近原型的第 l 个分量,则相关性向量的那些分量 l 仅略微增加。越接近意味着它们对特征向量的不正确分类的贡献越大。另一方面,如果特征向量的第 l 分量远离第 l 分量,则相关性向量中的该分量 l 显著增加。如果特征向量被正确分类,可以使用类似的动机。底线:该算法减少了导致特征向量被错误分类的那些λ分量,并且增加了导致特征向量被正确分类的那些特征向量分量。
那是一大堆理论。你就不能给我看看代码吗?
我以为你不会问了!关于这个理论更精确的定义,我参考了这篇论文。让我们来看看 Python 中的一个实现:
没有一些实验,这些代码当然没有任何意义,所以让我们在一些样本数据上尝试一下。
我们尝试的第一个数据集是一个人工数据集。它包括 2 个类,每个类有 50 个训练样本和 2 个特征。第一个特征呈正态分布,第一类的均值等于 2,第二类的均值等于 1。在两种情况下,方差都等于 0.5。第二个特征也是正态分布,均值等于 0,方差等于 0.5,并且在类之间没有差异。下图显示了上述人工数据集的曲线图。
人工数据集
如果我们分开来看每一个特性,很容易看出,仅仅用特性 2 是不可能把这两个类分开的。我们可以很容易地删除这个特征,并获得相同的分类性能。然而,有趣的是,RLVQ 是否可以识别这一点,而无需通过显式编程来忽略该特性。
训练 RLVQ 系统最困难的任务是将参数设置为最佳值。通常,为了找到正确的值,建议使用某种验证程序,但是为了这次演示的目的,我只是尝试了几个值,并决定将原型学习率和相关向量学习率都设为 0.01。通常相关向量学习率应该小于原型学习率,但在这种情况下,它工作得很好。
在人工数据集上运行该算法之前,我将特征向量进行了洗牌,并留出 10 %的集合作为验证集。在几个训练时期之后,RLVQ 在验证集上实现了大约 0.2 的误差。相关性向量得出特征 1 的相关性为 0.9,特征 2 的相关性为 0.1。很明显,它认为特征 2 对成功区分这两个类别没有太大帮助。由于这个问题仍然很简单,LVQ 得到了相似的分数。
让我们看看 RLVQ 在一些真实数据上的表现!在这种情况下,我使用了来自 UCI 机器学习库的钞票认证数据集。产生二元分类问题的这个数据集包含大约 1000 个具有 4 个特征的训练样本。和以前一样,数据集的 10 %被留出以验证模型。0.01 用于原型学习率,0.001 用于相关性向量学习率(可能不是最佳值)。RLVQ 产生约 14%的误差。这明显优于验证误差约为 30 %的常规 LVQ。
谢谢,还有别的吗?
与 LVQ 相比,RLVQ 的优势在于,它可以滤除非歧视性特征,同时仍然是易于理解的相当简单的算法。相关性向量还提供了对数据底层分布性质的一些洞察。因此,RLVQ 可以用作特征选择工具,为其他更复杂的算法预处理数据。
用 Python 进行可靠性分析
面向工业工程师的 Python
全面生产维护
可靠性
可靠性是一个项目在给定的一段时间内,在特定的操作条件下,执行所需的功能的概率**。换句话说,它是一段时间内无故障的概率。**
可靠性侧重于产品投入使用后继续发挥作用的时间(即产品的生命周期)。可靠性可以被视为进入时间域的质量。其公式表示为:
其中 f ( t )是给定分布的概率密度函数。
计算在时间 t 的产品/部件可靠性
计算特定时间的产品/部件可靠性需要多个步骤:
- 步骤#1:获取故障时间 — 定义样本量,获取每个产品/部件故障前的工作时间。
- 步骤#2:确定最符合数据的分布 —为收集的数据创建直方图,拟合多个概率分布,并确定最能描述数据的分布。
- 步骤#3:获取分布参数——获取所选分布的位置、尺度和附加参数,以确定其概率密度函数。
- 步骤#4:获得概率 —使用累积密度函数获得时间 t 之前的故障概率,使用生存函数获得时间 t 之后的可靠性。
对于下面的例子,让我们考虑一个工程师对分析一个特定产品的可靠性感兴趣。工程师获得了 1000 个样本的故障时间(以周为单位),并预计该产品至少在 40 周内完全可用。让我们来看看 Python 代码!
步骤#1:获取故障次数
第二步:确定最符合数据的分布
数据拟合了六种不同的分布:α、β、指数、γ、正态和瑞利分布。从上图可以看出,beta 分布是最符合数据的分布(这是显而易见的,因为样本是根据已知的 beta 分布生成的)。
步骤#3:获取分布参数
贝塔分布参数:
- a = 6.193
- b =1.978
- 位置= -1.035
- 比例=50.908
步骤#4:获得概率
根据结果,更有可能的是,该产品不会如预期的那样持续至少 40 周,因为其在 40 周之前的故障概率为 57.32%(即,其在 40 周之后继续起作用的概率为 42.68%)。
总结想法
在时域中,可靠性是产品质量的一个重要组成部分。客户希望产品在发生故障后补货前能持续一段时间。如果产品的功能时间不能满足客户的要求,在制造过程中必须对其设计规格进行更改。
本指南涵盖了如何使用多个 Python 库分析可靠性的分步教程。考虑到 Python 在专业人士和学者中的高受欢迎程度,Python 代表了一个能够执行统计分析的伟大工具。虽然有其他程序和统计软件能够分析可靠性(如 Minitab、R、Microsoft Excel),但质量和工业工程师应根据其编码和分析技能决定使用哪一种,同时遵守组织的目标和客户的规范。
— —
如果你觉得这篇文章有用,欢迎在 GitHub 上下载我的个人代码。你也可以直接在 rsalaza4@binghamton.edu 给我发邮件,在LinkedIn上找到我。有兴趣了解工程领域的数据分析、数据科学和机器学习应用的更多信息吗?通过访问我的媒体 个人资料 来浏览我以前的文章。感谢阅读。
——罗伯特
关于宗教的文本挖掘推文
使用 Python 的主题建模、情感分析和仇恨言论检测模型
有人声称科技革命的光芒将会削弱宗教在人类生活中的存在。然而,现在是 2020 年,有一件事似乎是不可避免的,宗教仍然在这里,并且会一直存在下去!也就是说,值得研究一下现代公众对宗教的看法。
这篇文章全面介绍了如何使用 Python 来提取、预处理和分析关于宗教的推文。该分析是关于实现主题建模(LDA)情感分析 (Gensim)和仇恨言论检测 (HateSonar)模型。下面的分步教程与代码和结果一起展示。
感谢 Johannes Schneider 博士和 Joshua Handali 理学硕士在列支敦士登大学指导这项工作。完整的代码可以在 GitHub 的这里找到。
列支敦士登瓦杜兹城堡
数据提取&预处理
为了获取 tweets,我们使用了一个公共 python 脚本,该脚本能够捕获旧的 tweets,从而绕过 Twitter API 的 7 天期限限制。该脚本是免费的,可以在 GitHub 的这里找到。你所需要做的就是调整搜索过滤器并运行程序。在我们的研究中,我们提取了包含短语*“宗教是”的推文*为了减少某些影响对宗教感受的孤立事件(如《查理周刊》袭击)的偏见,我们将时间范围延长至大约五年。我们从 2015 年 1 月开始到 2019 年 10 月,每月提取 1000 条推文。这产生了大约 57,351 条推文,然后被加载到数据帧中,准备进行预处理。
以下是整个分析过程的示意图
分析步骤
预处理
这些是执行预处理阶段所必需的包。
**import** pandas **as** pd
**import** numpy **as** np
**import** re# Plotting
**import** seaborn **as** sns
**import** matplotlib.pyplot **as** plt# Gensim
**import** gensim
**from** gensim.utils **import** simple_preprocess# NLTK
**import** nltk
**from** nltk.corpus **import** stopwords**from** collections **import** Counter
**from** wordcloud **import** WordCloud**import** warnings
warnings.filterwarnings("ignore", category=DeprecationWarning)%matplotlib inline
数据加载
df = pd.read_csv('full_data.csv', index_col=[0])
df.head()
数据概述
在任何进一步的步骤之前,我们删除重复的内容,因为在 twitter 上,人们复制粘贴不同的引用并转发某些内容是很常见的。删除重复后,我们总共得到 53,939 条独特的推文。
**# DROP DUPLICATES**
df.drop_duplicates(subset=['tweet_text'], keep='first',inplace=**True**)
df.shape
Out: (53939, 1)
接下来,我们生成一些一般的描述性统计数据:
描述统计学
Twitter 允许通过“@”符号在推文中包含用户名。这些对我们的分析没有任何价值;因此,使用函数将它们从数据集中移除。
**# REMOVE '@USER'
def** remove_users(tweet, pattern1, pattern2):
r = re.findall(pattern1, tweet)
**for** i **in** r:
tweet = re.sub(i, '', tweet)
r = re.findall(pattern2, tweet)
**for** i **in** r:
tweet = re.sub(i, '', tweet)
**return** tweetdf['tidy_tweet'] = np.vectorize(remove_users)(df['tweet_text'], "@ [\w]*", "@[\w]*")
规范化,一种将所有 tweets 转换成小写的方法,这样“token”和“Token”就不会被认为是两个不同的单词。
**# NORMALIZATION**
df['tidy_tweet'] = df['tidy_tweet'].str.lower()
与用户名一样,标签也被认为对主题建模分析没有重要价值,因此被移除。
以上是该数据集的前 25 个标签,我们注意到 #islam 是使用最多的标签,这表明它是讨论最多的宗教。使用以下函数移除标签:
**# REMOVE HASHTAGS**
**def** remove_hashtags(tweet, pattern1, pattern2):
r = re.findall(pattern1, tweet)
**for** i **in** r:
tweet = re.sub(i, '', tweet)
r = re.findall(pattern2, tweet)
**for** i **in** r:
tweet = re.sub(i, '', tweet)
**return** tweetdf['tidy_tweet'] = np.vectorize(remove_hashtags)(df['tidy_tweet'], "# [\w]*", "#[\w]*")
接下来要删除的是 URL:
**# REMOVE LINKS**
**def** remove_links(tweet):
tweet_no_link = re.sub(r"http\S+", "", tweet)
**return** tweet_no_linkdf['tidy_tweet'] = np.vectorize(remove_links)(df['tidy_tweet'])
使用与链接相同的功能,我们还删除了*收集词,*那些首先用于过滤推文的词,在这种情况下:宗教,“宗教”
之后,需要去掉数字、标点符号(仅用于主题建模),以及特殊字符(@、&、#、%).
**# REMOVE Punctuations, Numbers, and Special Characters**
df['tidy_tweet'] = df['tidy_tweet'].str.replace("[^a-zA-Z#]", " ")
然后,从数据集中移除少于三个字符的单词(短单词),从而简化用于分析的特征提取。
**# REMOVE SHORT WORDS**
df['tidy_tweet'] = df['tidy_tweet'].apply(**lambda** x:' '.join([w **for** w **in** x.split() **if** len(w)>3]))
预处理的一个基本步骤被称为*标记化。*它是根据空格分割文本的过程,每个单词和标点都保存为单独的标记。我们使用来自 Gensim 的 simple_preprocess 方法来执行这个步骤。
**# TOKENIZATION**
**def** tokenize(tweet):
**for** word **in** tweet:
**yield**(gensim.utils.simple_preprocess(**str**(word), deacc=**True**)) df['tidy_tweet_tokens'] = **list**(tokenize(df['tidy_tweet']))
接下来,我们删除没有分析价值的停用词,通常是冠词、介词或代词,例如,“a”、“and”、“the”等。默认列表可以根据需要进行调整和扩展。我们向包含 179 个单词的自然语言工具包(NLTK)的预定义列表中添加了一些新单词。
**# Prepare Stop Words**
stop_words = stopwords.words('english')
stop_words.**extend**([*'from', 'https', 'twitter', 'religions', 'pic','twitt'*,])**# REMOVE STOPWORDS**
**def** remove_stopwords(tweets):
**return** [[word **for** word **in** simple_preprocess(str(tweet)) **if** word **not** **in** stop_words] **for** tweet **in** tweets]df['tokens_no_stop'] = remove_stopwords(df['tidy_tweet_tokens'])
在预处理的最后一步,我们删除少于三个令牌的 tweets 这导致总共有 49,458 条推文需要在分析阶段进一步考虑。对于主题建模和情感分析,具有少于三个标记的文档不适合生成足够的信息。
**# REMOVE TWEETS LESS THAN 3 TOKENS**
df['length'] = df['tokens_no_stop'].apply(**len**)
df = df.drop(df[df['length']<**3**].index)
df = df.drop(['length'], axis=**1**)
df.shapedf.reset_index(drop=True, inplace=**True**)
现在,出于识别和可视化数据集的最常用单词的说明性目的,我们生成 200 个最常用单词的单词云。
Wordcloud (250 字)
预处理阶段的效果如下图所示,清理后的 tweets 长度大大减少。如图所示,大多数推文在预处理后都不到 10 个单词,不像原始推文那样有大约 20 个单词。在第二组图表中,随着推文长度从大部分推文的大约 150 个字符变为清理阶段后的大约 50 个字符,效果更加明显。这一阶段至关重要,因为它减少了维度,并为模型产生了非常有价值的表征,这将在接下来的部分中解释。
清洁效果
最后,我们将预处理后的数据帧保存为 pickle ,然后用于主题建模阶段。
df.to_pickle('pre-processed.pkl')
主题建模
这些是实现 LDA (潜在狄利克雷分配)算法所需的包。
**# IMPORTS**
**import** pandas **as** pd
**import** numpy **as** np
**import** networkx **as** nx
**import** itertools
**import** collections
**import** spacy
**from** pprint **import** pprint# Plotting
**import** matplotlib.pyplot **as** plt
**import** seaborn **as** sns
**import** pyLDAvis
**import** pyLDAvis.gensim# Gensim
**import** gensim
**import** gensim.corpora **as** corpora
**from** gensim.utils **import** simple_preprocess
**from** gensim.models **import** CoherenceModel
**from** gensim.models.wrappers **import** LdaMallet# NLTK
**from** nltk **import** bigrams
**from** nltk.stem **import** PorterStemmersns.set(font_scale=**1.5**)
sns.set_style("whitegrid")**import** warnings
warnings.filterwarnings("ignore", category=DeprecationWarning)**%**matplotlib inline
我们不打算深入解释 LDA 是如何工作的;详细内容可在[1]的原始论文中找到。LDA 算法的核心思想可以理解为一个生成过程,其中文档由一组主题 *T、*的概率分布定义,而离散单词的概率分布反过来建立每个主题。说到这里,我们加载预处理的数据:
df = pd.read_pickle('pre-processed.pkl')
df.head()
预处理数据概述
数据加载后,我们继续添加二元模型和三元模型。表达特定意思时经常一起出现的一系列单词。N 个单词的序列被称为 N 元语法,因为理论上 N 可以是任意长度;最常见的是成对的单词(二元单词)和一系列三个单词(三元单词)。首先,我们需要对 no_stop_joined 列进行标记化,并将其转换为一个包含每条 tweet 的标记的列表;我们将这个列表命名为 data_words ,如下所示:
**# TOKENIZE**
**def** sent_to_words(sentences):
**for** sentence **in** sentences:
yield(gensim.utils.simple_preprocess(str(sentence), deacc=**True**)) # deacc=True removes punctuationsdata_words = list(sent_to_words(data))
现在我们准备将二元模型和三元模型添加到我们的语料库中。
**# Build the bigram and trigram model**
bigram = gensim.models.Phrases(data_words, min_count=10, threshold=100)
trigram = gensim.models.Phrases(bigram[data_words], threshold=100)# Faster way to get a sentence clubbed as a bigram
bigram_mod = gensim.models.phrases.Phraser(bigram)
trigram_mod = gensim.models.phrases.Phraser(trigram)**def** make_bigrams(texts):
**return** [bigram_mod[doc] **for** doc **in** texts]**def** make_trigrams(texts):
**return** [trigram_mod[bigram_mod[doc]] **for** doc **in** texts]**# Form Bigrams**
data_words_bigrams = make_bigrams(data_words)
下图显示了我们数据集中的二元模型。我们可以注意到伊斯兰-和平-和平、耶稣-基督、科学-气候变化等的组合。
二元模型可视化
下一步是词汇化,这是许多文本挖掘应用的基本步骤。词汇化考虑了上下文,并将单词转换为其基本形式;例如,术语“拥抱”被转换为“拥抱”,最好的”被转换为“好的”对于词汇化任务,使用的包是 *spaCy,*一个开源库,其中有许多用于自然语言处理的预建模型。
**# LEMMATIZATION
def** lemmatization(tweets, allowed_postags=['NOUN', 'ADJ', 'VERB', 'ADV']):
"""[https://spacy.io/api/annotation](https://spacy.io/api/annotation)"""
tweets_out = []
**for** sent **in** tweets:
doc = nlp(" ".join(sent))
tweets_out.append([token.lemma_ **for** token **in** doc **if** token.pos_ in allowed_postags])
**return** tweets_out**# Initialize spacy 'en' model, keeping only tagger component
# python3 -m spacy download en**
nlp = spacy.load('en', disable=['parser', 'ner'])# **Lemmatization keeping only noun, adj, vb, adv**
df['lemmatized'] = pd.Series(lemmatization(data_words_bigrams, allowed_postags=['*NOUN*', '*ADJ*', '*VERB*', '*ADV*']))
在这一步之后,我们再次删除了重复项,因为由很少几个标记组成的短 tweets 在被词条化后可能会导致重复行。在这一步之后,我们有 48’013 个唯一的行。
另一个有用的技术是词干,这是将一个单词转换成其词根形式的过程。与前面提到的词干化不同,词干化是一种更激进的方法,因为后缀剪切经常导致无意义的英语单词。例如,单词“动物”将被词条解释为“动物”,但是搬运工斯特梅尔给出了“动画”我们决定实现这两者来帮助降维。
**# STEMMING**
stemmer = PorterStemmer()
df['stemmed'] = df['lemmatized'].apply(**lambda** x : [stemmer.stem(y) **for** y **in** x])
在构建 LDA 模型之前,我们必须创建两个主要输入:字典和语料库,它们是使用 Gensim 包中的函数创建的。
**# Create Dictionary**
id2word_stemmed = corpora.Dictionary(df['stemmed'])
**IN:** print(id2word_stemmed)
**OUT:** Dictionary(26748 unique tokens: ['also', 'bless', 'blood', 'deed', 'fact']...)\**# Create Corpus**
tweets_stemmed = df['stemmed']
**IN:** df['stemmed'][1]
**OUT:** ['piti', 'antonym', 'disast', 'human', 'live', 'piti']
以下是语料库的样子,它的长度为 48’013:
Gensim 给每个单词分配一个唯一的 Id,然后将语料库表示为一个元组 (word_id,word_frequency )。
**# Term Document Frequency**
corpus_stemmed = [id2word_stemmed.doc2bow(tweet) for tweet in tweets_stemmed]
例如,下面这条未经处理的推文:
@ wagner_claire 宗教和怜悯是反义词。一个是灾难,另一个是人性。我们可以没有宗教,但不能没有怜悯。然而我们拥抱着……”
在语料库中预处理之后,将呈现为元组列表:
[(11, 1), (12, 1), (13, 1), (14, 1), (15, 2)]
建立 LDA 模型
现在是我们初始化话题数量 *k=10,*的时候了,这些话题将会被调整。
**# Build LDA model**
lda_model_stemmed = gensim.models.ldamodel.LdaModel(corpus=**corpus_stemmed**,
id2word=**id2word_stemmed**,
num_topics=**10**,
random_state=**100**,
update_every=**1**,
chunksize=**100**,
passes=**15**,
alpha='**auto**',
per_word_topics=**True**)
在此步骤之后,我们可以直接生成主题或搜索最佳模型,使用一致性分数作为具有不同主题数量的每个模型的度量。
**# OPTIMAL MODEL**
**def** compute_coherence_values(dictionary, corpus, texts, limit, start=2, step=3):
coherence_values = []
model_list = []
**for** num_topics **in** **range**(start, limit, step):
model = gensim.models.wrappers.LdaMallet(mallet_path, corpus=corpus_stemmed, num_topics=num_topics, id2word=id2word_stemmed)
model_list.append(model)
coherencemodel = CoherenceModel(model=model, texts=texts, dictionary=dictionary, coherence='c_v')
coherence_values.append(coherencemodel.get_coherence())**return** model_list, coherence_valuesmodel_list, coherence_values = compute_coherence_values(dictionary=id2word_stemmed, corpus=corpus_stemmed, texts=df['stemmed'], start=**2**, limit=**26**, step=**3**)
下面是生成的每个模型的一致性分数,我们选择的最佳模型有 k=8 个主题。
建立模型并运行最佳模型后,我们将讨论以下主题:
解释:
Topic [0] 宗教&政治 不言而喻是用政治、控制、政府、民族、川普等术语来表示的。,这说明了宗教是一个敏感的方面,它的作用与政治有关。
主题【1】基督教 由包含基督教作为讨论主题及其代表性关键词(如教会、天主教、基督教等)的推文组成。对于主要属于西方世界、以基督教为主要宗教的说英语的观众来说,这样的话题是意料之中的。
话题【2】宗教&科学 关注的是宗教与科学之间永无止境的争论,这场争论在由技术革命引领的现代世界愈演愈烈。
话题【3】宗教教义,【6】个人信仰,【7】众说纷纭 以关键词为基准,似乎彼此更接近。
话题【5】伊斯兰教 是以伊斯兰教为主要讨论主题的推文集合。从标签数量和词频统计可以看出,伊斯兰教因其不同方面在社交媒体上受到高度讨论,引发了人们的不同反应。
下面给出了推文在各主题中的分布,我们可以注意到前三个主题更占主导地位:
情感分析(VADER)
该零件所需的包装如下:
**# IMPORTS
import** pandas **as** pd
**import** numpy **as** np
**import** seaborn **as** sns
**import** matplotlib.pyplot **as** plt
**import** spacy
**import** re
**from** pprint **import** pprint**import** nltk
nltk.download('vader_lexicon')
**from** nltk.sentiment.vader **import** SentimentIntensityAnalyzer
**from** nltk.corpus **import** stopwords**from** collections **import** Counter
**from** wordcloud **import** WordCloud**import** warnings
warnings.filterwarnings("ignore", category=DeprecationWarning)**%**matplotlib inline
VADER 代表用于情感推理的效价感知词典,由[2]开发为基于规则的情感分析模型。关于如何开发该模型及其特征的详细信息可在原始文件中找到(见参考文献)。它考虑到了标点符号,大写,程度修饰语,连词,在分配情感值时前面的三个字母:消极,积极,中性。这些特性使得 VADER 情感分析器在对推文等社交媒体文本进行分类时取得了显著的效果,并使其成为进行我们分析的合适工具。
由于 VADER 情感分析器的特性,预处理阶段与主题建模阶段略有不同,下面列出了所采取的步骤,而代码与预处理阶段相同。也可以在这里 访问所有代码 。
情感分析的预处理步骤
删除不必要的列后的数据概览
VADER 模式
**# Create an object of Vader Sentiment Analyzer**
vader_analyzer = SentimentIntensityAnalyzer()negative = []
neutral = []
positive = []
compound = []**def** sentiment_scores(df, negative, neutral, positive, compound):
**for** i **in** df['tweet_text_p']:
sentiment_dict = vader_analyzer.polarity_scores(i)
negative.append(sentiment_dict['neg'])
neutral.append(sentiment_dict['neu'])
positive.append(sentiment_dict['pos'])
compound.append(sentiment_dict['compound'])**# Function calling**
sentiment_scores(df, negative, neutral, positive, compound)**# Prepare columns to add the scores later**
df["negative"] = negative
df["neutral"] = neutral
df["positive"] = positive
df["compound"] = compound**# Fill the overall sentiment with encoding:
# (-1)Negative, (0)Neutral, (1)Positive**
sentiment = []
**for** i **in** df['compound']:
**if** i >= 0.05 :
sentiment.append(1)
**elif** i <= - 0.05 :
sentiment.append(-1)
**else** :
sentiment.append(0)
df['sentiment'] = sentiment
将模型应用于我们的数据后,我们为每条推文分配了以下情感分数。最后一列表示最终分类( 1 -正, 0 -中性, -1 -负)。
下图给出了推文对情感类别的总体分类结果,其中 42.2% (20’512)的推文被归类为正面。* 41.1% (19’957)被归类为负面,,其余 16.7% (8’109)的推文被认为是中性(既不正面也不负面)。就社交媒体上关于宗教讨论的情绪而言,公众意见似乎是平衡的。*
根据情感对推文进行分类
此外,我们可以使用词云来查看负面和正面的推文,以说明每个类别的主导词。
字云正面推文
最常见的词是与领域相关的词,如伊斯兰教、穆斯林、基督教、基督教*,而一些与情感相关的词是:爱、和平、支持、伟大、尊重、善良等。,这自然意味着该推文的正面情绪得分。*
词云负面推文
在负面推文的情况下,除了与领域相关的词之外,一些携带负面情绪的词有:、杀戮、仇恨、攻击、愚蠢、暴力、问题、邪恶、操、狗屎、等…
由于积极和消极情绪的观点几乎各半,积极的推文除了轻微的数字优势外,在复合得分方面也有微小的负差异,如下图所示。正面推文的平均值为 0.525122,而负面推文的平均值为-0.541433。
复合得分分布
当谈到具体的宗教时,大多数讨论都是针对伊斯兰教的,推文数量最高,经过预处理步骤后有 679 条推文,其次是基督教,有 127 条推文,然后是其他流行的宗教,如印度教、佛教和犹太教。
讨论最多的宗教
伊斯兰教是社交媒体上讨论最多的宗教。因此,我们特别仔细地观察了对伊斯兰教的看法。对谈论伊斯兰的推文进行情感分析得出了以下结果:
对伊斯兰教的感悟
使用相同的方法(VADER)对推文进行分类,分析结果显示 44.2% (295 条)的推文是正面的,而 38.7% (258 条)的推文是负面的,而 17.0% (113 条)被认为是中性的。
下表列出了关于伊斯兰教正面和负面推文中最常见的词汇。
基于伊斯兰情感的词频
现在,我们呈现 10 条最积极的推文:
十大正面推文
上面显示的推文被高度评为正面,其中第 10 条推文的复合得分为 0.9810,第 1 条推文的复合得分为 0.989。分类器产生了正确的标签,因为推文显然是积极的,没有隐藏潜在的讽刺或讽刺模式,这些模式破坏了句子的意思。有趣的是,在 10 条推文中,只有 4 条提到了上帝,这个词,而爱这个词在 10 条最积极的推文中有 7 条被提到了 16 次。一条是关于伊斯兰教的,两条是关于基督教的。其余的是关于宗教的一般观点,集中在与他人的关系上,即彼此相爱是一个人应该遵循的核心宗教原则。大部分推文(6/10)的评分为负 0.000;其他推文的负分非常小,因为这些词:教条、种族、不请自来的等。个人正面得分最高的推文是第 4 条,得分为 0.683,因为它七次提到了和平这个词,在不包含否定词的同时增加了句子的正面度。
同样,以下是最负面的 10 条推文及其各自的得分:
**
上面显示的推文被评为非常负面(负面意义上),其中第 10 条推文的复合得分为-0.982,第 1 条最负面的推文的复合得分为-0.988。很明显,分类器产生了正确的标签,因为推文是负面的,表达了对宗教或宗教团体(即穆斯林)的拒绝、厌恶和负面情绪。这张表上的一些主导词及其各自的频率是死亡(8)、伊斯兰教(6)、强奸(4)等。被提及最多的宗教是伊斯兰教,在表达负面情绪时,10 条推文中有 8 条关注伊斯兰教,而一条是关于基督教,另一条是关于印度的佛教/印度教。
仇恨言论检测(声纳)
用于对讨论宗教的推文进行分类的模型是基于[3]工作的预训练模型。这个模型被认为对我们的任务有用,调查关于宗教的推特上仇恨言论的存在,并对其进行测量。这将有助于对在线环境中的宗教景观有一个总体的了解。
此任务所需的软件包有:
***# IMPORTS**
**import** pandas **as** pd
**import** numpy **as** np
**import** seaborn **as** sns
**import** matplotlib.pyplot asplt**from** hatesonar **import** Sonar # This is the hate speech detection library**import** warnings
warnings.filterwarnings('ignore')*
该过程从在笔记本上加载数据帧格式的数据开始。这些数据由大约 48,500 条推文组成,这些推文没有经过预处理,因为模型被训练来处理输入以提取必要的特征。模型中使用的一些预处理步骤有:移除标签、移除链接、移除提及、标记化和使用波特斯特梅尔的词干化。
数据概述
声纳型号
现在,我们将这个分类模型应用于我们的数据:
***# Create an object of Sonar Hate Speech Detection**
sonar = Sonar()Class = []
hate = []
offensive = []
neither = []**def** hate_speech_classifier(df, Class, hate, offensive, neither):
**for** i **in** df['tweet_text']:
sonar_dict = sonar.ping(text=i)
Class.append(list(sonar_dict.values())[1])
hate.append(list(list(sonar_dict.values())[2][0].values())[1])
offensive.append(list(list(sonar_dict.values())[2][1].values())[1])
neither.append(list(list(sonar_dict.values())[2][2].values())[1])**# Function calling**
hate_speech_classifier(df, Class, hate, offensive, neither)**# Prepare columns to add the scores later**
df["Class"] = Class
df["hate"] = hate
df["offensive"] = offensive
df["neither"] = neither*
生成的数据帧如下所示:
结果概述
*模型应用后,由 48’528 条推文组成的数据集被拆分为三类 *仇恨言论、攻击性语言、既不 (表示既不仇恨也不攻击)。下图中的第一个图表给出了推文在这些类别中分布的总体结果。仇恨和攻击性的推文加在一起总共产生了 3802 条推文,占数据集的 7.83%。因此,没有问题的推文总共有 44726 条,占数据集的 92.16%。第二张图表显示了所谓的有问题推文的分布情况,仇恨言论导致了总共 232 条推文(占有问题推文的 6.10%),因为攻击性语言在这一类别中占主导地位,共有 3,570 条(93.89%)。
仇恨言论检测结果
有趣的是观察情感特征如何与仇恨言论分类结果相关联。下图显示了仇恨言论、攻击性语言、和【非 负面、正面、或中性等分类的推文分布。正如预期的那样,仇恨言论更多地出现在负面推文中,从数字上讲,60%(232 条中的 145 条)包含仇恨言论的推文是负面的。在攻击性推文的情况下,比例类似于仇恨言论,正如习惯上预期的那样,大多数推文:58.8%(3570 条推文中的 2089 条)包含负面情绪。从其余部分来看,1106 条或 30.98%是正面的,375 条或 10.50%被归类为冒犯性的推文是情绪中性的。**
通过情绪检测仇恨言论
下图显示了基于复合情绪得分的仇恨推文的分布。与负面推文相对应的左侧人口更多(60%的推文),这使得使用仇恨言论的推文在情绪上是负面的。
仇恨言论按复合情绪评分
现在我们呈现十大最可恶的推文:
**
十大最可恶的推文
在被归类为仇恨言论的 232 条推文中,上述推文的仇恨得分最高,第 10 条推文的仇恨得分为 0.676,第 1 条推文的仇恨得分为 0.870。从一般的人工分析来看,我们看到这些推文被攻击性的词语占据,如推文编号[4]。该模型被训练为通过关注仇恨词汇来克服攻击性语言和仇恨言论之间的细微界限。仇恨最主要的方面是种族。10 条最可恶的推文中有 8 条提到了白人,使用了像白人女权主义者、美国白人种族主义者、白人、白人民族主义、欧洲白人血统、白人男性和白人男孩俱乐部这样的词语。第[2]条推文表达了对穆斯林的仇恨,称他们的宗教过时、性别歧视、愚蠢、而第[7]条和第[8]条推文提到了犹太人。第 6 条推特是带有种族主义动机的仇恨言论,指的是黑人使用俚语词 niggas。
同样,我们也展示最具攻击性的推文:
**
十大最具攻击性的推文
*冒犯性语言评分在榜单中占据主导地位,因为第一条推文的评分从 96.9%到 98.9%不等。只有第 10 条推文提到了伊斯兰教,第 5 条推文使用了希伯来语,但没有明确的证据表明提到了犹太教。攻击性的推文中充斥着大量攻击性的词语,如 *bitch,出现在列表中 10 条推文中的 8 条。Tweets [3,5,6]包含强烈的性相关词汇,而只有 tweets [1,2]以比喻的方式使用短语“是我的宗教”。
结论
在清理和预处理步骤之后,数据被提取到 LDA 算法以执行主题建模。这一阶段旨在调查公众关心的与宗教相关的话题,从而调查宗教的多维性是如何在网上讨论中体现的。然后使用 VADER 情绪分析工具对这些推文进行情绪分析,以揭示公众对宗教的情绪,无论是负面、正面、还是中立*。最后,声纳是一种仇恨言论检测工具,用于调查和测量宗教讨论中是否存在仇恨言论和攻击性语言。*
结果显示,与宗教相关的公共讨论最相关的话题是宗教&政治*、宗教&科学、基督教和伊斯兰教。情绪分析显示,公众对宗教的情绪存在分歧,42.2% (20’512)的推文被归类为积极的。41.1%(19957 例)为阴性,其余为中性。这些结果可以用来论证现代社会已经接受的世俗化和宗教归属的水平。仇恨言论检测工具提供的证据表明,社交媒体上确实存在以宗教为动机的仇恨言论和攻击性语言。总共有 3802 条推文或 7.83%的数据集包含仇恨言论(232 条推文)或攻击性语言(3570 条推文)。这表明宗教是一个公众意见分歧的领域,可能会在他们的讨论中激发仇恨和攻击性语言。因此,社交媒体平台应该做出更多努力来防止他们的用户在他们的在线讨论中的这种滥用行为。*
谢谢你
参考文献
[1]布莱博士,Ng,A. Y .,&乔丹,M. I. (2003 年,第 1 期)。潜在狄利克雷分配。(拉弗蒂编辑。)机器学习研究杂志,993–1022。
[2]休顿,C. J .,&吉尔伯特,E. (2014 年)。VADER:基于规则的社交媒体文本情感分析的简约模型。第八届 AAAI 网络日志和社交媒体国际会议。密歇根州:AAAI 出版社。
[3]t .戴维森、d .瓦姆斯利、m .梅西和 I .韦伯(2017 年)。自动仇恨言论检测和攻击性语言问题。第十一届 AAAI 国际网络和社交媒体会议。蒙特利尔:AAAI 出版社。
重塑我们自己
我从人文学科走向工程的道路
这是一篇长长的、详细的、非常诚实的文章,在这篇文章中,我讲述了挑战我的失败,以及我所做的正确选择,我对此心存感激。这是写给一小群朋友和熟人的自我反省和自我冥想。如果你,一个亲爱的陌生人,在我的作品中找到任何灵感或安慰,我会感到巨大的喜悦和成就感。
我写这封信不是为了让许多人看,而是只为了让你看:因为我们彼此都是对方的听众。
–伊壁鸠鲁
TL;速度三角形定位法(dead reckoning)
没有相关的大学学位背景,在软件工程领域开始职业生涯是具有挑战性的。这当然是一条有回报的道路,但正如我的故事所表明的那样,我们必须有信念,极其努力地工作,每天学习,设定正确的期望,并继续重塑自己,以便在幸运降临时抓住机会。无论我们想做什么样的职业支点,成功的关键是通过不断的学习和大量的试错,找到我们的激情和市场需求之间的甜蜜点。
感谢硅谷,软件工程是 21 世纪最(过分)荣耀的工作之一。每天越来越多的人对进入其他领域的软件感到好奇。
2016 年 4 月开始编程。2020 年 4 月开始软件实习。2020 年 7 月,我正式成为一名初级软件工程师,加入了终身学习者的行列,他们在一个最具活力、不断变化的领域中玩耍和劳作。
这篇博文主要是写给自己的。从我最亲密的朋友那里得到的反馈,我希望它代表了我所面临的所有失败、我所采取的正确行动,以及我在寻求职业成就的过程中所表现出的个性的真诚、坦率的陈述。
如果这篇文章有任何外部动机,那么它将分享我的信念,无论你对什么职业感兴趣,学习如何通过在不熟悉的领域获取知识和学习新技能来重塑我们自己是我们今天应该学习的最重要的技能之一。
换句话说,拥抱你感兴趣的知识,不管你是不是为了学位而学的。
回到原点
我的故事开始于 2006 年秋天,当时我以优异的成绩进入中国福建一所最负盛名的高中。在我所在城市的一年一度的高中入学考试中,我在我的中学排名第一,并且是前 30 名最好的学生之一。我的血液充满了自信,我觉得自己是一个聪明的饼干,注定会变得伟大。
黑客和画家:启发我编程的第一本书之一
大约在这个时候,我在阅读了 Eric S. Raymond 的博客文章的中文翻译,如何成为一名黑客和保罗·格拉厄姆的黑客和画家的几个翻译不好的章节后,对黑客产生了钦佩。Raymond 和 Graham 的作品揭示了黑客的个性和品质,以及黑客社区的精英性质,这与我当时尚未形成的价值观产生了深刻的共鸣。(注:史蒂文·利维的《黑客:计算机革命英雄》是我十几年后才接触到的一本很棒的书。)。
在我高中时已经懂编程的好朋友的鼓励下,我报名参加了高中提供的周末 Pascal 速成班。在一个灾难性的、潮湿的周六早晨,当我走进一个满是蓝色 DOS 屏幕的房间时,我吓坏了。
我生长在一个不允许我花太多时间玩电脑的家庭,那时候我甚至不能用五个手指正确地打字,更不用说使用 DOS 和用一种叫做 Turbo Pascal 的可怕语言写if-else
语句或for-loops
了!更糟糕的是,除了我之外的所有人似乎都能跟上速成班的节奏。
Turbo Pascal 的 DOS 和它的语法让我十年没有编程了(无意冒犯 Pascal!)
出于某种原因,盯着那个蓝色的屏幕,我无法理解计算机是如何思考的。我也不能写下任何一行代码来执行超过一个标准:
program Hello;
begin
writeln ('Hello, world.');
end.
我感到紧张,头上冒汗。老师让我们解决一些更基本的问题,但我的大脑感觉像一锅煮过头的粥。我坐在那里,呆若木鸡,呆若木鸡,而其他所有的学生都在埋头苦读,互相分享他们的兴奋。
到了午休时间,我偷偷溜出教室,回家了。在我所在城市的一些最好的学生中,我觉得自己非常愚蠢。
在接下来的几周里,我尝试了Java
、C
和C++
,这些语言是我表哥为了他在一所大学的计算机科学课程而学习的。然而,每次我都不知道如何在父亲的 Windows 电脑上安装这些语言的软件。我试着在纸上写代码,但即使是最简单的#include <stdio.h>
对我来说也太复杂了,更不用说冗长的Java
。
然后,迟早有一天,我放弃了,并得出结论,我不是编程的料。从那一刻起,编程成了那个尴尬、屈辱的早晨的痛苦回忆,我脆弱的自我不允许承认我没有自己想象的那么聪明。
我是如何开始学习 Python 的
时间快进到 10 年后的 2016 年,我已经获得了德克萨斯 A&M 大学的历史学士学位,并获得了久负盛名的优等成绩和 Phi Beta Kappa 荣誉社团的钥匙。我不知道该如何生活,也不喜欢准备法学院入学考试(LSAT),于是在瑞士圣加仑一所著名的商学院攻读学士学位。
在那里,在那个美丽的瑞士小镇,我进入了一生中最艰难的两年。当我的同学在瑞士联合银行、高盛和麦肯锡等公司面试时,我在瑞士或德国都找不到商业实习机会。事实上,从我发出的众多申请中,我只得到一次面试机会,而公司录用了另一位候选人。
哪儿也不去。卡住了。我知道我错过了什么,但我不知道是什么。在德克萨斯 A&M 成为明星后,我觉得自己在瑞士是个彻头彻尾的失败者。
完全出于运气,我联系到了一位法兰克福的价值投资者,这位校友好心地给了我一些时间和我聊天。我们在 St. Gallen’s Altstadt 喝咖啡时进行了愉快的交谈,然而,在此期间,他很快就认定我缺乏在他的基金中担任实习生所需的所有财务和会计知识。
感觉到他敏锐而准确的判断,我绝望地问道:
"我应该学习哪些对你的基金有价值的技能?"
他回答道:
你可以考虑学习 Python 和 编程 进行机器学习。如今,技术也开始进入价值投资领域。”
我觉得我的胃马上打结。当我走回家时,言语无法形容我的沮丧和失望。我当时含着眼泪打电话给我的女朋友,向她抱怨说,我在这个世界上最不想做的事情就是再次学习如何编程,这位投资者毫不夸张地告诉我,我应该学习编程的 Python 。我被打败了,那天很早就上床睡觉了,但却无法入睡。
第二天早上,我仍然心不在焉,我咬咬牙,在网上搜索可以教我Python
的课程。我找到了一些免费资源,设法在我的 Windows 笔记本电脑上安装了Python
,并开始编程。
立刻,我意识到事情有所不同:我没有像和Pascal
、C
或C++
在一起时那样目瞪口呆。文本编辑器中没有神秘的、不可思议的脚本代码。很简单。我的 hello world 程序(用Python2
语法)只有一行:
print "Hello, world."
我内心仍然充满不确定和恐惧,我告诉自己,这一次,我可能真的会带着Python
到达某个地方。这就是我开始编程的真实故事。
多编码遇到深度学习
我想真诚地感谢吉多·范·罗苏姆和所有的核心开发人员,因为他们创造了一种美丽的语言,吸引了我们这些被 T8 吓到的人。
在通过在线书籍艰难地学习 Python和 Coursera 的 Python for Everybody 学习了基本的 Python 语法和一些编程概念后,我对编程有了一些信心。我把我的操作系统从 Windows 换成了 Ubuntu,这是一个流行的 Linux 发行版,作为一种将编码作为一种生活方式的姿态。
我还没有爱上编程。有时候,当我遇到一个我无法理解的新概念时,我从 2006 年开始对电脑的恐惧会再次出现,我必须给自己时间冷静下来,回到电脑屏幕前。
但是对于一个陷入自怜和停滞不前的职业道路的学生来说,编程是一种奇怪的解放。因此,即使是在终端制作一个无用的、错误的基于文本的游戏,对我来说也是一种很好的消遣,让我从枯燥的经济学考试中解脱出来,我必须记住这些考试。
没有任何刻意的目的,我学到了越来越多的东西,比如如何双启动 Ubuntu 和 Windows,如何使用终端和命令行,如何写一个小脚本来从 YouTube 上报废搜索结果,下载 YouTube 视频。我写得越多,编程就变得越有趣。我知道没有人会使用我写的任何程序,但不管怎样,我为它们感到骄傲。
到 2016 年秋天,我经过深思熟虑,决定不在圣加仑完成学业,而是开始在斯德哥尔摩经济学院攻读硕士学位。一方面,我想结束异地恋,另一方面,我希望斯堪的纳维亚能为我停滞不前的职业发展提供机会。
作为我的项目中唯一能够用通用编程语言编写脚本的学生,我越来越深入其中。当我的同学在研究咨询案例时,我在学习如何模块化我的代码的同时,黑进了我的文本编辑器和终端来渲染一个 Hangman 游戏。当我的同学在晚上聚会和社交时,我坐在地下室继续学习在线数学和编程课程。作为一群商科学生中唯一对计算机的魔力有所了解的人,我感到很自豪。
在我的编程之路上,最有影响力的在线课程之一是哈佛的 CS50。(来源: CS50x 在维基媒体共享许可下)
大约在这个时候,我完成了麻省理工的 6.00.1x 和 6.00.2x ,开始做哈佛的 CS50 课程,最终完成了其中 70%的作业。我爱 CS50 和它的人民。直到今天,它仍然是所有在线课程中最好的,我把它推荐给我所有想学习编程的好朋友。
不久之后,我也发现了 Udacity 关于深度学习的新节目。由于不知道什么是深度学习,我报名参加了这个课程,因为它听起来很酷(现在你可以通过像 fast.ai 这样的免费资源学习)。我学习了反向传播、卷积神经网络、图像分类、长短期记忆(LSTM)和生成对抗网络(GAN)。所有这些都不容易,我肯定无法独自完成所有的事情。哇哦!我可以训练一个“神经网络”来识别图像中的数字!
与我最早的编程经历非常相似,我经常对深度学习感到目瞪口呆,但我坚持了下来,因为这个主题很有趣,也因为我认为我没有其他竞争优势。
一次又一次的失败,直到幸运降临
为了更好地消化我的知识,我开始写博客。我很荣幸我写的两篇关于深度学习基础的文章(帖#1 和帖#2 )总共邀请了超过 24 万的浏览量。(注:我从来没有找到时间和精力来完成关于反向传播的第三篇博客。这里有一篇来自 Christoph Olah 的关于反向传播 的惊人的 帖子。
这些小小的成功增强了我的信心,我决定寻找有趣的人工智能初创公司,申请在柏林的产品、营销或 bizdev 实习。在读了林恩·鲁特向工程转型的故事后,我想过申请工程职位,但我退缩了。不管怎样,我联系了当时能找到的所有创业公司。
这个循环又重复了一遍。我不是被拒绝就是被忽视。
我记得我申请的一家初创公司回信说,他们没有适合我的职位,但一个月后我发现他们从圣加仑聘请了另一个我感兴趣的人。这在那一刻伤害了我的自尊心,但事后看来,我从来没有把这些决定放在心上。初创公司往往缺乏大型人力资源团队来消化所有的申请,有时,没有被错误的雇主聘用是一件好事。
在我沮丧的时候,福尔图娜夫人降临在我身上。我联系了莫里茨,一个完全陌生的人,他当时是一家深度学习初创公司 TwentyBN 的产品所有者。那时,我几乎已经放弃了在柏林找实习的机会,只是因为莫里茨的情况与我相似,我想我可以为自己的职业道路寻求一些建议。我点击了他 LinkedIn 个人资料上的按钮,发了一条短信。
一条简单的 LinkedIn 信息改变了我的职业生涯
我不知道这条消息让我得到了一份实习和全职工作,最终允许并鼓励我转向软件开发。(注:2017 年 10 月,在我开始在 TwentyBN 实习之前,我曾短暂地参与了一个开源项目OpenMined,试图获得更多的软件经验。那次经历也让我害怕,因为我不理解 Git、Github、单元测试和 CI/CD。我以工作为借口暂停了它,直到 2020 年 4 月,我成为 TwentyBN 的一名软件实习生。)
对职业道路不满意
我做了两年的产品营销人员,但没有一天我觉得这是我的使命。我接受这份工作是因为我完全相信 TwentyBN 的员工和我们的技术,但我不喜欢社交媒体。我想为公司的成功做出贡献,但从未改变对社交媒体营销的想法。在这个职位上,我没有什么长进,也从未感到满足。
在这段时间里,我经历了一次友好的分手,但还是伤了我的心。而且,我暗暗感到自己的位置在公司里被边缘化了。我的薪水增加了,但在我内心深处,我对自己不能扮演一个更有意义的角色感到沮丧。我在瑞士体验到的那种压抑的感觉似乎又在上升。
虽然我的一部分继续沉迷于一些偶尔晚上的编码会议和书呆子编程语言活动,但我不认为软件对我来说是可能的。我觉得我已经太老了,不能再回到初级职位重新开始。
在我对职业道路不满意的那段时间,我尝试了很多事情,包括为我的公司经营一份名为 Embodied AI 的时事通讯
在工作中,我开始撰写和编辑我们公司的简讯 Embodied AI 。私下里,我开始在一份名为 Plutarch 的时事通讯中把我的阅读清单变成关于领导力的书评和分析。
怀着为我的作品建立声誉的愿望,我开始尝试并试图吸引人们注册这两份时事通讯。我尝试了各种营销渠道,被多个 Reddit 子网站封杀,最终为 Embodied AI 管理了大约 500 名订户,为我的个人通讯管理了大约 100 名订户。
就我自己而言,我采纳了朋友克里斯的建议,克服了我对健身房的恐惧,开始尝试举重和健美操,这完全超出了我的舒适区。
健身给了我多巴胺和睾丸激素。但是我的通讯尝试没有给我带来满足感。在将近一年的时间里,我继续进行了各种各样的小型实验。然而,我对职业的不满仍在继续。
转行不嫌老
2019 年底,我对工作的长期不满表现为一场存在主义危机(2020 年的冠状病毒加剧了这一危机)。
我得出了一个严峻的结论:如果我再继续做 10 年的产品营销,我会恨自己没有采取任何行动。
我脑海中的这个声音再次暗示了软件。
早在 2018 年,我就想向 TwentyBN 申请深度学习工程实习生的实习机会,但我缺乏信心,无法晋级。到 2019 年底,我从熟人那里听到了足够多的成功故事,他们在训练营后找到了软件工作,这让我重新燃起了探索软件工程作为职业生涯的愿望。
在我回中国的圣诞节假期中,我花了整整 3 周的时间和哈佛的 CS50W 一起学习 web 开发,从早上 8 点一直编码到晚上 1 点或 2 点。我想用这种密集的体验来测试自己,看看我是否有能力成为一名程序员,或者这只是一个阶段。学习曲线很陡,防火长城阻止我轻松访问 Google 和 StackOverflow。但是我管理了两个 bug 项目,学到了一些Flask
、Django
、Javascript
和WebSocket
。
黑客新闻上的这个帖子让我相信,我仍然可以转行,而且我还不算太老
在这三周里,最具变革性的是,在将近 14 年的时间里,我第一次感觉到自己又回到了第九区。我全神贯注于编程。一整天我都在思考如何解决这些项目和问题。我甚至做了 2-3 个梦,在梦里我找到了代码的解决方案。
编程比产品营销更适合我。从本质上来说,市场营销是一项非常困难的工作。病毒营销和增长营销是研究得很透彻的话题,但没有人能 100%肯定地说,一个产品或一家公司的成功是否是由某个单一的策略或行动造成的。
然而,编程是致命的逻辑。我被它迷住了,因为我喜欢这种即时的满足感,因为有时,即使一行代码的改变也会导致巨大的视觉差异。当我最终调试了我的代码并巩固了我的学习成果时,虽然有时单调乏味和令人沮丧,但也给了我巨大的回报。这比我过去两年做的好多了!
最后,在那几周我工作非常努力,直到我从中国回到柏林才听说了 COVID19。
回到工作岗位后,我认为自己还不算太老,不适合尝试软件工程。我成功说服了我的老板 Moritz、我的 Python 团队领导以及我的 CTO Ingo 给了我三个月的带薪实习。又是一个不眠之夜,无数次的头痛。减薪是可以控制的,但是我对没有成功的紧张和我的冒名顶替综合症给我的心灵增加了很多压力。
然而,到现在为止,我的编程经验教会了我什么是我的学习模式,我对自己也变得更有耐心了。我稳步学习,解决门票,寻求帮助,最终,实习变成了一个新的全职职位。
重塑我们的“自我”
有一个无条件支持我的家人和好朋友帮助了我。有重视教育并在我最糟糕的时候慷慨支持我的父母帮助了我。接受一个陌生人的建议很有帮助。学过编程和深度学习有帮助。学过历史专业并有良好的写作技巧对此有所帮助。与我公司的管理层和同事们志趣相投,这帮助了我。所有这些帮助都是必要的。
但同样重要的是,我还必须感谢福尔图娜夫人,是她把我塑造成了这样一个人,他有学习新的、看似令人畏惧的技能的动力,用自律和坚韧重塑自我。如果没有这种不断学习的习惯,我不可能取得我想要的成就。
您可能已经知道,我作为软件学徒的学习之旅才刚刚开始。软件工程是一个充满活力的领域,有许多有才华的人和优秀的想法。我仍在学习如何编写好的软件,以及如何跨多个团队工作。
这是我日复一日工作的一群了不起的人
四月,我重新联系上了开源项目 OpenMined 的创始人。我开始再次贡献我有限的能力,以便让自己更多地接触其他编程语言,磨练我作为开发人员的整体技能。这并不容易,但 OpenMined 社区是一个了不起的团体。
此外,我必须弥补一些知识缺口,比如架构设计、模式设计,以及众所周知的算法和数据结构。我很清楚这些差距,并将继续努力。毕竟我报了一个只有继续学习才有效果的职业。
拉芬
我们中的大多数人不会有像火箭一样一帆风顺的职业生涯。我们大多数人注定会在生活中的某个时刻遭遇职业僵局。我们大多数人都有能力做些什么。
对我来说,那包括了近十年的转专业和思考我会对哪一行工作充满热情。
在我穿越美国和欧洲的旅途中,每一站都要面对挫折和拒绝。这是我人生中第一次没有通过工商管理专业的考试和两门考试。这包括对我的职业道路不满两年。
但就像狄更斯写的那样,这是最坏的时代,但也是最好的时代。感谢所有现在或曾经在我生命中的人,我活了下来。失败挑战了我对自己优点和缺点的认识,但没有一次失败摧毁了我。
每次我被击倒,我都会哭一会儿,然后站起来,从学习新知识和获得新技能中寻找安慰。没有放弃。
今天我在这里。一个新的旅程刚刚开始,我对我将在旅程中学到的所有令人兴奋的事情感到兴奋。我非常有信心,各种各样的失败和拒绝将继续向我走来。我确信我会有弱点和挫败感的时候。但是我已经经历了很多,我知道我足够强大,足以承受所有这些,并继续重塑我自己和我的生活。
在过去的几年里,我对别人隐瞒了大部分的失败。我的一部分仍然为他们感到羞耻。但我决定把它们写下来,作为自我反省的一种形式。此外,我知道有人正在经历类似的经历。也许这些话会有帮助。
所以给你。这个故事是给你的,我希望,尽管它很长,我的历史能引起你的共鸣或启发你,这样你最终也能重塑你的生活。祝你好运,永不放弃。
欢迎联系我或在 Twitter 上关注我!
星球大战第四集(1977 年)重新制作
一个深度学习管道来重新制作被删除的场景
图片由阿格尼耶斯卡·科瓦尔茨克在 Unsplash 上拍摄
TLDR
这是模型的输出。左边是重制输出。右为原创视频。
用于训练和跑步推理的完整 Jupyter 笔记本可在 Github 上获得
被删除场景的新希望
我是《星球大战》的超级粉丝。和许多星战迷一样,我也迷上了卡通频道和迪士尼+的《星球大战:克隆人战争》。这是一场非凡的演出。
但是当我看旧的东西时,我总是对视频质量的下降感到恼火。例如,这里是从《星球大战:第四集:新的希望》(1977)中删除的场景。这是第一部被创作出来的星球大战。
视频由马塞洛·祖尼加
这些奇怪的黑色眼镜不断出现。难怪这些是被删除的场景。
显然那些奇怪的规格被称为提示符号。它们是胶片上划痕留下的痕迹。《星球大战》是一部很棒的剧集,但它也很古老。
深度学习最近被用于视频恢复。结果非常有希望。例如,Deoldify 允许用户给旧视频和图像着色。 NVIDIA 的 Noise2Noise model 可以让人们将旧图像恢复到曾经的辉煌。
但到目前为止,据我所知,还没有什么东西能专门去除旧胶片上的“记号”和粒状斑点。所以让我们来建造它吧!
创建数据集
创建数据集很棘手,但仍然可行。我是这么做的。我从 youtube 上下载了高质量的视频。然后我毁了他们。我添加了黑色眼镜,降低了视频的分辨率。Ffmpeg 在这方面非常有用。
首先,我们将下载视频。
youtube-dl --format best -o seinfeld.mp4 [https://www.youtube.com/watch?v=nEAO60ON7yo](https://www.youtube.com/watch?v=nEAO60ON7yo)
我在用这个视频。我用的是《T2》中宋飞的一个片段。为什么不呢?
视频由系列制作
那我们就要毁了它。为了做到这一点,我从 youtube 上下载了一个颗粒状的电影叠加。然后我用 ffmpeg 叠加视频,混合设置为柔光。找到正确的混合设置需要大量的试验和错误。ffmpeg 文档没有很多例子。
现在我们有两个视频。一个质量很好,另一个质量很差。
作者提供的视频
作者提供的视频
现在我们将从每个视频中提取帧。最初,我采用了一种天真的方法来做这件事。我会在 python 中浏览视频并单独抓取每一帧。但这花了太长时间。我最终意识到,我们可以在这里使用多处理来真正加快速度。这是根据海登·福尔克的剧本改编的。
太好了。现在我们有两个数据集。一个劣质图像(取自受损视频)和一个优质图像(取自高质量视频)。为了让这些垃圾图片更垃圾,我会缩小它们(虽然这不是必要的步骤)。
def resize_one(img, size): targ_sz = resize_to(img, size, use_min = True)
img = img.resize(targ_sz, resample = PIL.Image.BILINEAR).convert('RGB')
return img
这就是现在蹩脚的正常图像的样子。旁注:这是《宋飞正传》中一个很棒的场景。
作者图片
作者图片
快速检查显示,我们有大约10014
个文件的数据集。非常好。
神经网络
让我们通过使用转换来充分利用这些10014
文件。
我添加了水平和垂直翻转,缩放变化,灯光变化和旋转变化。使用 Fastai,这真的很容易做到。
以下是一些图像转换。
作者图片
还不错!
我们将在这些数据上使用 fastai 和 jason antic 首创的 NoGAN 网络。这个代码的灵感来自 fastai 课程的第 7 课。
我在 google colab 的免费 GPU 上训练了这个模型。他们是一个伟大的资源,我不能相信他们是免费的。
培养
fastai 推荐的有趣的事情是逐渐增加你的图片的尺寸。
因此,首先,你在小尺寸图像上训练,然后你升级你的图像,在大图像上再训练。这会节省你很多时间。相当聪明。
首先,我们将在大小为 128x128 的图像上进行训练。因为图像太小了,我可以把批量增加到 64 张。
我为此选择了一个1e-2
的学习率。我想要一些有攻击性的东西,但仍然是安全的爆炸。这已经被证明非常有用。
作者图片
网络将在训练期间打印结果。输入在左边,预测在中间,目标在右边。结果看起来很有希望!
作者图片
我调整了尺寸,再次训练。再一次。每次我把尺寸调整得比以前稍微大一点。我将视频帧的尺寸从 128x128 改为 480x480。
作者图片
这是最后一班火车。为此我使用了pct_start = 0.3
。我想在培训期间减少 70%的学习时间。在微调模型时,我更喜欢较低的学习率。这次训练的结果看起来非常好。
作者图片
推论:适用于星球大战
一旦这个网络训练完毕,我就进行推理。这比我原先想的要复杂得多。
我必须下载星球大战删除的场景(使用 youtube-dl ),然后提取这个视频中的所有帧。我提取帧使用相同的方法之前。
作者图片
然后我不得不在视频的每一个单独的帧上运行来自学习者的推断。那需要很长时间。
我在这里添加了一些黑客。
首先,我添加了渲染因子。这是从解密中截取的。这个想法是,我缩小图像,并将其转换为一个正方形。然后我对那张图片进行推理。该模型更容易接受正方形的图像。这已经被显示为大大减少了“故障”。
在正方形图像上运行推理后,我将它转换回原始形状。我发现这可以减少故障,通常会导致更平滑的视频输出。我将render_factor
设置为40
,虽然如果我们想要更高的分辨率输出,它可以更高。不过,我可能需要更大的内存。
第二,我调节亮度。这不是真正的黑客。似乎更像是一个错误,我是正确的手动。出于某种原因,模型推断导致图像亮度非常低。
我怀疑这与我们之前用于 ffmpeg 的softlight
过滤器有关。但是我必须在这里手动更正。我需要进一步调查此事。
第三,我使用 matplotlib 的保存功能。我发现 fastai 的保存图像功能给了我非常奇怪的结果(Luke 的衣服是荧光蓝色和红色)。但是奇怪的是,matplotlib 的保存功能给了我很好的结果。我需要调查这件事。我怀疑我可能会损失图像的质量,因为我正在使用 matplotlib 的savefig
功能。
这是模型的一些输出。
作者提供的图片
作者图片
作者图片
然后我不得不把所有这些画面拼接在一起,制作一个视频。为了做到这一点,我最初使用 ffmpeg,但我结束了我的 RAM 超载。相反,我用了 opencv2 的VideoWriter
。
这是最终的输出。
作者提供的视频
和原始视频
视频由马塞洛·祖尼加
丰富
- 天空需要更多的工作。但是我喜欢背景的活力。这是一个有趣的(完全没有计划的)效果。目标是从视频中删除“提示标记”(恼人的黑色规格)。我认为在这方面已经做得很好了——但是还有更多的事情要做。
我喜欢网络是如何强化了阳光的。当比格斯说他要加入反抗军时,卢克和比格斯之间的场景完全改变了。
原始帧(左)。网络输出(右侧)
2.在22
秒标记周围出现了一条奇怪的横条线。我没有在训练集中添加任何水平条,所以完全可以理解网络根本没有删除它。但是在未来,我需要在我的训练集中增加更多的单杠来解决这些问题。
3.我也在考虑对视频做更多的超分辨率处理。高质量地展示一个年轻的卢克·天行者会很不错。为了做到这一点,我可以在进一步训练之前调整图像的大小。我已经缩小了图像,但我还可以进一步缩小。
或者,为了实现 superres,我可能会使用现成的升级工具,比如 VapourSynth 。这可能是最好的选择,因为原始视频的质量已经很差。
4.推论也是一个问题。它会导致内存过载和崩溃。结果是,42
秒是我在这个视频中能得到的最长时间。我不完全确定如何解决这个问题。但是如果我要进一步使用它,我需要解决它。
这么多事要做!
完整代码可从 Github 获得
原载于 2020 年 6 月 19 日https://spiyer 99 . github . io。
远程数据科学团队
提高远程团队效率和效力的 5 个关键
由于降低新冠肺炎传播的努力,绝大多数数据科学团队现在都在远程工作。
不幸的是,许多团队不习惯远程工作,因此不知道在远程数据科学团队工作时需要考虑的挑战。
最重要的是——团队需要使用充分理解和沟通的流程!因此,如果需要,请查看www.datascienceprocess.com获取数据科学特定流程培训的帮助。
有了定义良好的流程,并关注下面概述的 5 个关键点,团队可以有效地提供所需的可操作的洞察力。
1:考虑多变的工作环境
与工作环境相比,有些人的家庭工作环境效率较低(例如,家里有孩子)。考虑到这一点,为了实现同步协调,需要平衡人们在“正常”时间工作的部分时间与人们在最适合他们的时间工作的灵活性…
对一些人来说,在家工作时很难被激励(因为有无数的可能分心的事物)。因此,某种结构——就预期的可交付成果和沟通而言,可以帮助团队成员保持专注。
3:关注项目协调
为了帮助确保一个项目能够得到有效的协调,需要有效地确定任务的优先次序、分工并分享成果。
- 确定任务的优先顺序:直观地传达任务的优先顺序(例如看板)有助于确保团队在最重要的任务上保持一致,并有助于保持项目发起人/利益相关者/产品所有者的参与。
- 划分工作:团队应该确保每个人都了解如何在数据科学团队中有效地划分工作,以及如何在团队中有效地整合工作。
- **分享结果:**分享在执行任务时获得的知识,通常需要的不仅仅是分享生成的代码或解释生成的可视化效果,还需要分享生成的更高层次的见解(如发现不应进一步探究的死胡同)
4:促进讨论和交流
当数据科学团队远程工作时,有些事情,比如能够走过去和某人交谈,是不可能的。团队可以复制这些类型的交互,但这些交互需要更多的思考,因为在远程工作之前,它们可能不是团队当前文化和常规的一部分。因此,团队应该:
- 组织团队沟通:同步更新很重要(例如,每天的单口相声对远程团队非常有效)。但是正在进行的讨论也很重要,也需要被促进(例如,通过 slack 的异步讨论)
- 继续集思广益:集思广益是数据科学项目的一个重要方面,但当每个人都远程时,很容易被忽视,因此需要鼓励团队在每个人都远程时进行集思广益(例如,潜在的可行见解、潜在的新数据源)。利用所需远程工作的一种方法是,例如,在会议之前使用异步投票,以获得一些最初的头脑风暴想法,然后可以进行讨论。虽然这种方法(以及其他方法)对于同处一地的团队也是可行的,但是由于团队成员可能会脱离,因此更加有意识地思考如何让团队参与进来会给远程团队带来更多好处。
5:不要忘记团队文化
由于每个人都很疏远,很难保持团队文化(态度、社区等),在这种情况下,随着一切的进行,团队很容易疏远,团队文化也很容易消失。因此,应该付出额外的努力来帮助确保积极的文化,团队应该明确地决定重要的文化问题(可能会被隐含地决定),例如:
- 一天中应该有多少时间是同步 vs 异步?
- 工作日需要多少重叠?
有关其他数据科学项目管理的见解,请查看www.datascience-pm.com。最后,为了帮助团队建设,我最近启动了远程欢乐时光(每个人都带着自己喜欢的饮料参加视频会议,在会上人们讨论与工作无关的事情)。
远程开发变得简单
图片来自 Unsplash 上的 @domenicoloia 。
PyCharm 提示和技巧
对我来说,PyCharm 中的< 5 minutes!
Configure once, then connect each time! Image created by the author.
P ycharm 是一个很棒的 IDE——拥有促进有效编程的特性,一个致力于分享聪明的插件的社区,以及我最喜欢的特点专业许可证对学生免费。有了它, JetBrains toolbox 及其许多 ide(一种最现代的计算语言)可供学生免费使用(没有任何附加条件)。好样的,脑残!对学生免费是更多产品应该拥抱的服务。
至此,让我们进入正题——通过 PyCharm 远程工作。
随着冠状病毒成为国际关注的焦点,很大一部分专业人士必须远程工作(包括我自己)。随着我设置一台 iMac(即本地机器)与运行 Ubuntu 的 PC(即远程主机)同步工作,下一步就是配置 PyCharm 在本地编辑,远程运行。这样做有很多原因——我的动机是用 GPU 将作业部署到远程主机。这不是我第一次经历这个过程,每次都要回忆。我认为这值得做笔记并在媒体上分享。尽情享受吧!
注: 以下步骤描述了使用 JetBrain 的 PyCharm 进行远程设置。然而,对于所有 JetBrain 产品(例如,【web storm】、【IntelliJ】以及作为 JetBrains 一部分的其他产品)来说,这是相同的过程。
设置远程主机
通过 PyCharm 的部署工具设置远程主机非常简单(也就是说,PyCharm 提供的大多数特性都是如此)。对此,几句话就够了。尽管如此,在本教程中准备了详细的步骤,以确保清晰。我们开始吧!
具体来说,我们的目标是建立一个 SFTP 连接,一个运行在 SSH 协议上的安全文件传输模式。为此,我们必须知道以下几点。
- 通过ifconfigbash 命令可以访问主机的 IP 地址。
- 主机上的用户名(在(1)中相应的 IP 地址上)
- 密码或一个 SSH 密钥(为了简单起见,这里将使用密码——未来的博客可能在 SSH 密钥上)。
现在,有了 1–3 的知识,我们在本地机器上配置 PyCharm。
从这里开始,gif 值 1000 个单词:
从菜单栏的 工具 *中打开 配置… *。作者创造的形象。
随着展开窗口打开:
创建新的 SFTP 连接。作者创造的形象。
设置配置(即,参见上面的 1–3)。作者创造的形象。
将映射设置为主机上项目的根目录。注意远程浏览器(左)用绿色突出显示映射的文件(即,相同名称的文件,相对于映射根,被假定为映射)-由作者创建的图像。
通过最底部的工具面板查看远程主机,其中保存的更改被确认传输到主机—作者创建的图像。
N ow,修改可以自动上传,如下图所示。
设置 【自动上传(总是) 【开】 —图片由作者创作。
N 注意,现在*自动上传(总是)*选项被取消。
自动上传截图(总是) 切换“开” —图片由作者创作。
答或者,手动处理同步有多种方式。
浏览远程主机并右键单击要同步的文件(无论是与主机同步还是从主机同步)。请注意,上面截图中显示的复选标记不再显示——图片由作者创建。
瞧啊。就这样,我们都被设置为远程工作!
概括起来
免责声明。 Pycharm 是 2016 年从 MATLAB 过渡时最有意义的偏好(即,相似的外观和感觉)。也就是说,还有其他有希望的替代方案,其他人可能会认为更好(例如, Atom 、 Visual Studio 、 Spyder 等等)。参见2020 年 11 个最佳 Python ide根据guru 99——不,我没有选择这个列表仅仅是因为 Pycharm 被列为第一;)在下面的评论中分享你最喜欢的 IDE。
最后一点——我花了很多时间学习 PyCharm,因为它是我日常使用的工具。那么,了解一种提高生产率的新手段是否值得呢?它不仅值得,而且势在必行——vim、Emacs 等等。,非常适合快速访问远程文件;然而,现在是 2020 年,人们,让我们利用我们所掌握的技术;)
旁注
像 PyCharm 这样的工具隐藏了许多基本概念:初级研究人员不会为了节省几分钟的时间而损害深刻的理解。不要学习 PyCharm 的来龙去脉,除非知道 Python 的基础知识,并且正在并行理解一个中级知识。否则,总有一天,像 PyCharm 这样强大的图形界面不是一个选择。一个人必须能够执行 still(相信我,如果这对你来说不明显,那么这意味着你可能应该学习构建 python 项目和系统路径的基础)。这里列出了其他一些值得一读的博客:
- 如何构建一个 Python 项目,作者米沙·贝里恩。
- Jeff Hale撰写的《成功建立 Python 项目的 10 个步骤。
- 千篇一律的学习和发展——过去对我来说很有效。
有大量关于上述主题的信息。因此,如果你寻找的答案不在一个或多个参考文献中,那么评论和链接会被提供。如果没有链接,那么将创建一个博客——童子军的荣誉。
我希望这有所帮助。对这个或未来应该涉及的话题提出意见、建议或问题!如果有什么特别好的地方(例如,gif 相对于文本和图像的使用)或不好的地方(例如,细节太少),请让我知道,以便更新它,并让我在构建未来的博客时考虑。
感谢您的阅读:)
在 LinkedIn 、 Twitter 、脸书上关注罗宾逊博士
Joseph P. Robinson 在 Vicarious Surgical 从事外科机器人研究……Robinson 博士获得了东北大学电气和计算机工程学士学位(2014 年)和计算机工程博士学位(2020 年)。
www.jrobsvision.com。](https://www.jrobsvision.com/)
阅读更多由约瑟夫·罗宾逊博士在媒体上发表的文章
个人最喜欢的一句俏皮话
towardsdatascience.com](/pandas-tips-tricks-need-for-speed-54e217cc6aa0) [## 对图像数据集进行重复数据删除的绝佳方式
生产中的命令行工具
towardsdatascience.com](/a-great-tool-for-image-datasets-cb249663ca45) [## 减少杂乱,适应空间
变得有条理、高效甚至舒适的 3 个技巧
jvision.medium.com](https://jvision.medium.com/reduce-the-clutter-adapt-the-space-6daeef2e2ca9)
远程工作——新标准?
数据驱动分析,更好地了解远程工作
我们真的需要去办公室吗?(照片由阿维·理查兹在 Unsplash 上拍摄)
我花了三个月远程工作。可能还会持续好几个月。我以为我会讨厌它。但是……不一样!谷歌宣布了 2020 年剩余时间的在家工作政策。脸书采取了类似的政策。Twitter 告诉其员工他们可以无限期地继续远程工作。在我们生活的时代,阻止病毒的唯一方法是在我们的生活中嵌入社交距离。大多数员工最近都开始在某种程度上远程工作。在家工作可以让员工更快乐,并为员工和雇主省钱。远程工作是新的标准吗?
人们可能会有关于远程工作的紧迫问题,以及有什么比揭示数据告诉我们什么更好的方式来回答这些问题。所以我找到了 2019 年由 Stack Overflow 进行的年度开发者调查的公开数据,其中包括大约 88K 开发者的回复。因此,这里的背景基本上与在软件/IT/数据科学行业工作的人相关。以下是我在数据中发现的一些有趣的事实。
远程工作的开发人员对工作更满意吗?
对我来说,这是最重要的问题,要了解远程工作的人对他们的工作有多满意。
工作满意度分布
事实上,大多数全职远程员工对他们的工作非常/稍微满意!从非远程员工到全职远程员工,非常满意的员工有明显增加的趋势。此外,我将这些回答转换为 5 分制的李克特量表,得出平均工作满意度分数。远程工作文化对工作满意度有很强的正相关性。
工作满意度得分上升趋势
因此,有了在任何地方工作的灵活性,开发人员似乎对他们的工作更满意了!我们真的需要去办公室吗?
远程工作者挣得多吗?
由于全球疫情,全球大部分地区的员工都被降薪,因此在做出任何决定之前了解收入情况非常重要。让我们比较一下远程工作的开发人员和其他人的工资水平。
开发人员的平均年薪
有趣的发现是,可以在去办公室和远程工作之间做出选择的员工平均收入最高。远程工作者的收入明显高于他们的同事。
远程工作面临的最常见挑战是什么?
我们的发现告诉我们,远程工作实际上更好——但肯定会有一些相关的挑战。在我远程工作的几个月里,我确实遇到了一些问题,但是像往常一样,我们不要做任何假设,而是看看我们的数据告诉我们什么。
远程工作面临的挑战
远程工作面临的最常见的三大挑战是会议、分散注意力的工作环境和非工作任务。非工作承诺包括必须照看孩子和做家务。我当然更喜欢面对面的会议,在家里会感到心烦意乱。然而,随着各种视频会议工具及其功能的日益流行,分析下一年的年度调查将会很有意思。
远程工作在什么类型的组织中受欢迎?
到目前为止,如果你已经下定决心要找一份远程工作,让我们问一下数据,你应该寻找哪种类型的组织。
当我们分析数据时,我们意识到远程工作文化在小型组织中很普遍。相当比例(大约 70%)的远程工作者在员工少于 100 人的组织中工作。所以你远程工作的最佳选择是加入一个小组织或者自己创业!
这里的发现是观察性的,是我从数据中发现的,不是正式研究的结果。所以真正的问题仍然是:
远程工作——新标准?
如果你已经走了这么远,谢谢你的阅读。我上面所做的是巧妙地应用了 CRISP-DM ,这是一种处理数据科学问题的流行方法。让我们来揭示这个简单的方法是如何应用到这个项目中的。结束时,你也可以开始应用它了!
乌达城的描述性图片
- 业务理解—当我开始远程工作时,我想了解与此相关的几个因素,这促使我提出这些问题。大多数数据科学问题源于一系列基本问题,首先识别这些问题至关重要。
- 数据理解—查找或收集可以回答您的业务问题的数据。我怎么强调花足够的时间从里到外理解数据都不为过。这对以下所有步骤的帮助比你想象的要大。
- 数据准备——从来没有现成的原始数据可供使用。虽然堆栈溢出为我们提供了基本的数据清理,处理异常值,丢失值,分类值是强制性的。
- 分析/建模——探索性数据分析足以回答我们的问题。然而,一些复杂的问题可能需要进一步建模,以获得预测洞察力。
- 评估—可以使用几种统计测试来评估和获得结果。在建模的情况下,评估指标通常用于评估所提议的解决方案的性能。
- 部署——一些问题需要部署某种产品,而另一些问题需要将洞察力传达给利益相关者*(这正是这篇博客所做的!).从现在起,也许我会对全职远程角色更加开放?*
这篇博客有意省略了包括代码在内的复杂而详细的分析,把它们留给了 GitHub 库,如果你需要进一步理解的话。您是否从远程工作的数据中发现了其他有趣的见解?或者这已经说服你去尝试远程工作了?我很乐意听到各种反馈!
从时间序列数据中移除非线性趋势
有时需要从时间序列数据中移除趋势,为后续步骤做准备,或者作为数据清理过程的一部分。如果你能确定一个趋势,然后简单地从数据中减去它,结果就是去趋势数据。
如果趋势是线性的,你可以通过线性回归找到它。但是如果趋势不是线性的呢?一会儿我们会看看对此我们能做些什么。
但是首先,简单的例子。
线性趋势
以下是有趋势的时间序列数据:
https://raw . githubusercontent . com/FlorinAndrei/misc/master/qdata . CSV
让我们加载它,看看它看起来像什么:
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from sklearn.linear_model import LinearRegression
from sklearn.preprocessing import PolynomialFeatures
from sklearn.metrics import mean_squared_error, r2_scoreser = pd.read_csv('qdata.csv', index_col=0, squeeze=True)
serx
0 473.917764
1 75.324825
2 -306.969479
3 53.271476
4 372.966686
...
95 4650.550473
96 4604.573344
97 4891.704638
98 5265.948162
99 5618.909339
Name: y, Length: 100, dtype: float64plt.plot(ser)
plt.show()
好吧,这是一个趋势。让我们假设它是线性的——让我们进行线性回归并找出答案。这是线性回归的直接应用。上面导入的 sklearn 库有我们做回归所需的一切。
X = ser.index
X = np.reshape(X, (len(X), 1))
y = ser.valuesmodel = LinearRegression()
model.fit(X, y)
trend = model.predict(X)plt.plot(y)
plt.plot(trend)
plt.legend(['data', 'trend'])
plt.show()
似乎很合适,但可能不太合适。让我们从数据中减去趋势,看看去趋势后的数据是什么样的:
detr = [y[i] - trend[i] for i in range(0, len(y))]
plt.plot(detr)
plt.title('data detrended in a linear fashion')
plt.show()
不太有说服力。数据中仍有一个凹趋势。或许最初的趋势并不是线性的。
让我们计算数据和我们提取的趋势之间的 RMSE 和 R 值。我们稍后将回到这些数字。
r2 = r2_score(y, trend)
rmse = np.sqrt(mean_squared_error(y, trend))
print('r2:', r2)
print('rmse', rmse)
r2: 0.8782399672701933
rmse 553.6078593008505
多项式瞧
如果趋势不是线性的,我们可以尝试用多项式曲线来拟合。但是事情是这样的:即使我们拟合的曲线是一个高次多项式,它仍然是线性回归,将被用来找到它。怎么会这样
好吧,考虑这个二次表达式:
y = a + bx + cx
我们寻找的值是 a、b 和 c,它们都是线性的(1 的幂)。忘了 x 的幂,我们看的是 a,b,c 的幂,还记得为什么广义线性模型叫“线性”吗?因为系数是线性的,所以 x 值可以有不同的幂。
所以是线性回归——只是碰巧我们必须一次做多维的线性回归。
让我们假设我们的数据有一个二次趋势。然后我们需要将 X 转换成二次形式:
pf = PolynomialFeatures(degree=2)
Xp = pf.fit_transform(X)
Xp
看起来像这样:
array([[1.000e+00, 0.000e+00, 0.000e+00],
[1.000e+00, 1.000e+00, 1.000e+00],
[1.000e+00, 2.000e+00, 4.000e+00],
[1.000e+00, 3.000e+00, 9.000e+00],
[1.000e+00, 4.000e+00, 1.600e+01],
[1.000e+00, 5.000e+00, 2.500e+01],
[1.000e+00, 6.000e+00, 3.600e+01],
...
[1.000e+00, 9.600e+01, 9.216e+03],
[1.000e+00, 9.700e+01, 9.409e+03],
[1.000e+00, 9.800e+01, 9.604e+03],
[1.000e+00, 9.900e+01, 9.801e+03]])
第一列是 X 的 0 次幂。第二列是 X。第三列是 X 的 2 次方。这就好比上图所示的二次表达式(y = a + bx + cx)。
现在,我们将使用二次形式来拟合数据,并生成二次趋势。使用线性回归找到二次表达式的参数。
md2 = LinearRegression()
md2.fit(Xp, y)
trendp = md2.predict(Xp)
趋势是什么样的?
plt.plot(X, y)
plt.plot(X, trendp)
plt.legend(['data', 'polynomial trend'])
plt.show()
很合身,不是吗?现在让我们看看去趋势数据:
detrpoly = [y[i] - trendp[i] for i in range(0, len(y))]
plt.plot(X, detrpoly)
plt.title('polynomially detrended data')
plt.show()
这显然更好。那里没有留下任何可以视觉识别的趋势。但是让我们看看数字是怎么说的:
r2 = r2_score(y, trendp)
rmse = np.sqrt(mean_squared_error(y, trendp))
print('r2:', r2)
print('rmse', rmse)
r2: 0.9343217231542871
rmse 406.5937924291518
与线性趋势相比,多项式趋势 R 增加,RMSE 减少。两者都是好的改变。两个平均多项式比线性拟合更好。
高次多项式
您可以选择任意阶的多项式,只需在此处为 N 指定不同的值:
pf = PolynomialFeatures(degree=N)
一般来说,使用较低的 N 值。如果 N 值增加,但变化不大,则返回较小的值。
有一个弯曲的曲线可能可以用二次函数来描述。有两个弯曲的曲线可以用三次函数来描述。诸如此类。N-1 次弯曲需要一个 n 次幂的表达式。
如果你增加 N 很多,最终你的“最佳拟合”曲线将开始跟随数据中的噪声,而不是拟合趋势。你过度拟合了曲线,现在已经没有意义了。要么减少 N,要么增加更多的数据点。
移除 ML 操作中的“墙”
ML Ops 试图为机器学习提供一个持续改进的过程
越来越多的团队正在寻求采用一种叫做 ML Ops 的方法。ML Ops 得名于十年前出现的 DevOps 运动,它试图为机器学习提供一个持续改进的过程。随着 Dev Ops 现在被早期采用者相当好地建立起来,并且它所提供的商业价值的证据变得越来越清晰,将 DevOps 的解决方案直接应用到机器学习团队是很有诱惑力的。
然而,为了成功实施这种方法,有必要了解开发运维服务早期的经验教训以及它试图解决的问题的性质。
在 DevOps 之前——“墙”
在 DevOps 运动之前,开发传统上由开发团队组成,在将大的包中的变更交付给运营团队进行测试和部署之前,开发团队独立地处理特性。
这两个团队是自我隔离的,拥有不同的目标和技能集;开发团队致力于开发新的特性,而运营团队致力于提高系统的整体性能。
将团队想象成具有不同目标和活动的独立实体,在他们之间建立了一堵隐喻墙,阻止每个人理解另一个团队的挫折和障碍。你看不到的,你无法理解或寻求补救。
是什么促成了 DevOps
为了转变这种方法,实现我们称为 DevOps 的更具凝聚力的运营方法,需要改变思维方式。墙的两边都有共同的参照点。尽管在工作实践和技能组合上存在差异,但是两个团队都希望更顺利的部署和发布过程,并希望通过改进的反馈与业务目标更紧密地联系在一起。
在两个团队之间建立这种共同点导致了实践中的变化,DevOps 就是这个变化的同义词。
团队之间的墙的拆除允许更好地理解系统的整体性,以及允许反馈和改进在团队之间容易地传播。用户也从这一变化中受益,因为两个团队的员工现在更能响应他们的需求。
例如,使数据库运行更慢的特性以前会被视为操作问题,但在 DevOps 的思维模式下,它变成了每个人的问题,并被协作解决。
来自 2018 和 2019 的开发运营报告表明,开发运营思维的改变直接提供了可衡量的业务价值,因为它对内部和外部需求给予了同等的重视。这两个团队之间的技能集现在有大量的重叠,开发、测试和生产环境变得几乎相同。
ML 操作的情况
在机器学习领域,目前只有大约 10%的项目真正交付了商业价值,显然有必要进行类似的革命。术语 MLOps 自 2017 年以来才被广泛使用,因此没有像 DevOps 那样得到很好的记录或定义,但本质上,MLOps 的目的是为机器学习提供与 DevOps 对开发和运营同样的价值。
对于我们这些从事机器学习的人来说,我们可能渴望一个和谐的未来,在这个未来,我们将拥有一个全自动的机器学习 CI/CD 系统,拥有多技能的员工,能够理解彼此的需求和目标,并平等对待他们。
更重要的是,我们希望机器学习能够通过快速适应需求来推动业务价值,并快速发现问题。在我们的未来愿景中,一个装备精良的 MLOps 团队应该能够很容易地识别和解决数据/算法/模型中的问题,并通过一个易于使用的 ML 平台快速适应业务需求和数据偏差。
为了达到这个目标,团队需要欣赏 DevOps 所涉及的相互理解之旅,不要试图跳到上面列出的快乐结局。与此同时,还有更大的障碍需要克服,不花时间去理解“墙”的真正本质,直接跳到一个解决方案上,将无法解决根本问题。首先,我们需要识别现有的问题,这样我们就可以避免潜在的陷阱并交付。
通常,在机器学习项目中,需要许多团队和技能。我们可以大致将其分为两组,每组都有不同的需求和目标,就像我们之前将开发人员和运营专家分开一样。
研究人员和数据科学家希望利用企业收集的数据来解决复杂的问题。他们关心的是解决方案的性能,包括诸如精确度和召回率、模型大小或培训成本等指标。
开发人员和工程师更加传统,通常按照我们之前制定的 DevOps 原则工作。他们的主要关注点是吞吐量、减少延迟、降低成本、增强功能等目标。
上面的墙可以以多种不同的形式存在。任何阻碍研究兴趣和开发/运营兴趣之间融合的事情都会造成这堵墙。例如:
进入生产系统
面向工程师的代码分叉/存储库
数据访问/操作
团队之间缺乏信任
沟通障碍
寻找共同点
通常,这两个团队的业务目标是相同的。与 DevOps 一样,两个团队都希望在为业务开发和部署解决方案时减少挫折。也就是说,将更多的时间用于创造商业价值的项目,减少令人沮丧的管理费用。
机器学习的共同点一般归结为两点:数据和代码。
数据
数据是迄今为止最重要的资产,任何试图利用机器学习的公司都需要很好地处理它。整个公司可能会因为他们处理数据的方式而消失。使用数据作为公共基础是一个棘手的过程,通常需要难以理解的单一数据湖或复杂模式。
然而,没有这种统一会在研究团队和工程团队之间建立一堵墙。如果来自生产系统的数据不能容易地以相同的格式流入训练数据,那么完全实现 MLOps 将变得越来越复杂。
密码
类似地,代码库可能会成为一堵墙,威胁到 MLOps 解决方案的进展。将“实时”和“研究”的存储库分开,将存储库分成不同的分支,所有这些都会导致完全采用 MLOps 的问题比它们在短期内解决的问题更多。这在很大程度上归结于研究人员和工程师之间不同的标准。当研究人员需要快速迭代、测试假设和创建最小解时,工程师希望看到健壮的、可伸缩的、经过良好测试和组织的代码。
你必须找到一个公司所有成员都同意的中间立场,这样整个公司的标准才是一致的。这有一个额外的好处,可以减少团队之间的挫折感,因为他们无疑会认为自己的标准比交给他们的代码“更好”。这造成了团队之间的敌意,从而强化了这堵墙。
系统访问
我们经常听说不允许研究人员访问工程资源、参与讨论或访问完整的生产驱动数据。类似地,工程师不能参与概念讨论,也不能访问培训系统,因此在面对已决定的解决方案时,他们也不能接受。最终,这归结为信任。你相信你的员工和团队成员会做正确的事情吗?他们觉得能够在不被斥责或忽视的情况下提问吗?
第一步
我将在以后的文章中更详细地介绍其中的一些,但是现在,我们可以总结一下更容易过渡到 MLOps 所必需的重要步骤。
- 采用开放、统一的元数据层,在整个管道中共享。
- 创建一个普遍认可的标准,并确保团队按照这个标准一起工作。
- 考虑将其他团队的资源嵌入到您的项目中。
- 像信任自己的团队一样信任其他团队成员。
- 利润!(或者,更准确地说,不断改进这一过程……)
在熊猫数据帧中渲染图像
有没有想过在数据帧中渲染图像?我很高兴你这么做了!
照片由 艾米莉·莫特
我能看到 问号(?) 在你的大部分脸上。因为在发现我们也可以在数据帧中渲染图像之前,我也有一个。相信我,这很简单,你所需要知道的就是 创建一个数据框架,然后我会从那里 接你。
要遵循的步骤
- 导入
**pandas**
**HTML**
两个必要的库。 - 创建一个你选择的熊猫数据帧,并存储在变量
**df**
中。 - 创建一个名为
**country**
的列表,然后存储您想要渲染的图像的所有路径。 - 将
**country**
列表分配给现有的数据帧**df**
。这将作为一个新列附加到现有数据帧中。 - 写一个函数,把给定的图片路径转换成 HTML 标签。
- 将 dataframe 呈现为 HTML 表,然后调用 HTML 方法来显示呈现的图像。
奖金
此外,我将向你们展示“ ”保存数据帧为 HTML 页面 ”更像一个网页。
密码
按照上面的步骤 1-6 成功渲染数据帧中的图像。我也将在这里重复这些步骤。不必每次都向上滚动阅读。同样,完整的代码可以在我的 GitHub 资源库 下面找到:
permalink dissolve GitHub 是超过 5000 万开发人员的家园,他们一起工作来托管和审查代码,管理…
github.com](https://github.com/Tanu-N-Prabhu/Python/blob/master/Rendering_Images_inside_a_Pandas_DataFrame.ipynb)
导入**pandas**
****HTML**
两个必要的库。**
导入**pandas**
库的原因是为了在数据帧中创建和存储数据。类似地,**HTML**
库用于呈现 dataframe 中的图像(HTML 标签)。
**# Importing the necessary libraries**import **pandas** as **pd**
from **IPython.core.display** import **HTML**
不需要使用
**pip**
命令手动安装,只需导入即可******
创建一个你选择的熊猫数据帧,并存储在变量 **df**
中。
这一步很简单,因为几乎每个人都知道如何创建数据帧。如果没有,那么别忘了在这里浏览一下这篇 文章 。我将通过从world ometers . info获取 COVID19 数据来创建 dataframe。请记住这个数据每小时都在变化。我将制作五个不同的列,如**Total Cases**
**Total Deaths**
**Total Recovered**
**Total Tests**
**Population**
。对于行,我会选择**USA**
**Brazil**
**Russia**
**India**
**Peru**
。****************************
****# Create a dataframe using pandas library**df = pd.**DataFrame**([[2768571, 130655, 1155027, 34713051, 331002277], [1448753, 60632, 790040, 3070447, 212558178], [654405, 9536, 422931, 19852167, 145934619], [605216, 17848, 359891, 8826585, 1379974505], [288477, 9860, 178245, 1699369, 32969875]], **columns** = ['Total Cases', 'Total Deaths', 'Total Recovered', 'Total Tests', 'Population'])**
创建一个名为 **country**
的列表,然后存储你想要渲染的图像(标志)的所有路径。
这一步是显而易见的,为了保持一致,我们将创建一个列表,其中包含上面列出的所有国家的国旗路径。国旗来源可以在这里 找到 。
****# Create a list named country to store all the image paths**country= ['https://www.countries-ofthe-world.com/flags-normal/flag-of-United-States-of-America.png','https://www.countries-ofthe-world.com/flags-normal/flag-of-Brazil.png','https://www.countries-ofthe-world.com/flags-normal/flag-of-Russia.png','https://www.countries-ofthe-world.com/flags-normal/flag-of-India.png','https://www.countries-ofthe-world.com/flags-normal/flag-of-Peru.png']**
将 **country**
列表分配给现有的 **df**
数据帧。这将作为一个新列附加到现有数据帧中。
这是最简单的步骤之一,因为您需要将名为**country**
的列表分配给 dataframe 名为**Country**
的新列。
****# Assigning the new list as a new column of the dataframe**df['Country'] = country**
当你打印数据帧**df**
时这样做。你会得到下面的结果。
塔努·南达·帕布拍摄的照片
编写一个函数,将图片(链接)的给定路径转换成 HTML 标签
这里你需要写一个将链接转换成标签的函数,正如你在前面的结果(Dataframe)中看到的,Country 列有所有的链接,所以这一步是必要的。
****# Converting links to html tags**def **path_to_image_html**(path):
return '<img src="'+ **path** + '" width="60" >'**
该函数的返回类型是传统的**img**
标签,我们用它来呈现网页上的图像。如果你不知道我在说什么请看 这个 。这样做的原因是,如果所有的路径都被转换成图像标签,那么最后在一个内置的 HTML 方法的帮助下,所有这些都将被呈现为图像。
将数据帧渲染为 HTML 表格,然后调用 HTML 方法显示渲染后的图像
我们将使用**to_html**
方法将数据帧转换成 HTML 表格。有一些参数我们需要处理,首先是**escape = False**
,转义 HTML 标签,我们需要调用**path_to_image_html**
方法,将其转换成一个字典,并将其分配给 formatters 内置变量。欲知此法详情,请访问 此处 。
****# Rendering the dataframe as HTML table**df.to_html(escape=False, formatters=dict(Country=path_to_image_html))**
通过执行这个操作,您将得到一个您熟悉的 HTML 表格。下面我将只提供第一个表行快照:
塔努·南达·帕布拍摄的照片
而最后要做的就是调用内置的**HTML**
方法,将整个 dataframe 作为参数传递。
****# Rendering the images in the dataframe using the HTML method.****HTML**(df.to_html(escape=False,formatters=dict(Country=path_to_image_html)))**
最后,当你执行这个,你会得到你想要的。
塔努·南达·帕布拍摄的照片
奖金
正如我所承诺的,我将向你们展示如何将数据帧保存为 HTML 页面。当你想给你的老板或任何人发送大量带有图像的数据帧时,这通常会很有帮助。
****# Saving the dataframe as a webpage**df.**to_html**('webpage.html',escape=False, formatters=dict(Country=path_to_image_html))**
如上所述,你只需要提供保存网页的路径,因为我用的是我的 Google Colab ,它会保存在我的笔记本环境中,打开它你会看到如下所示的结果。
塔努·南达·帕布拍摄的照片
完整代码
本教程的完整代码可以在下面找到:
****# Importing the necessary libraries** import pandas as pd
from IPython.core.display import HTML**# Create a dataframe using pandas library** df = pd.DataFrame([[2768571, 130655, 1155027, 34713051, 331002277],
[1448753, 60632, 790040, 3070447, 212558178],[654405, 9536, 422931, 19852167, 145934619],[605216, 17848, 359891, 8826585, 1379974505],[288477, 9860, 178245, 1699369, 32969875]], columns = ['Total Cases', 'Total Deaths', 'Total Recovered', 'Total Tests', 'Population'])**# Create a list named country to store all the image paths** country = ['https://www.countries-ofthe-world.com/flags-normal/flag-of-United-States-of-America.png','https://www.countries-ofthe-world.com/flags-normal/flag-of-Brazil.png','https://www.countries-ofthe-world.com/flags-normal/flag-of-Russia.png','https://www.countries-ofthe-world.com/flags-normal/flag-of-India.png','https://www.countries-ofthe-world.com/flags-normal/flag-of-Peru.png']**# Assigning the new list as a new column of the dataframe** df['Country'] = country**# Converting links to html tags** def path_to_image_html(path):
return '<img src="'+ path + '" width="60" >'**# Rendering the dataframe as HTML table** df.to_html(escape=False, formatters=dict(Country=path_to_image_html))**# Rendering the images in the dataframe using the HTML method.** HTML(df.to_html(escape=False,formatters=dict(Country=path_to_image_html)))**# Saving the dataframe as a webpage** df.to_html('webpage.html',escape=False, formatters=dict(Country=path_to_image_html))**
写这篇文章的主要灵感来自于这个关于堆栈溢出的论坛。特别感谢chitown 88。
假设我有一个想要导出为 PDF 的数据帧。在数据框中,我有以下几列:代码,名称,价格…
stackoverflow.com](https://stackoverflow.com/questions/53468558/adding-image-to-pandas-dataframe)
谢谢大家,这就是这个教程,我希望你们今天学到了一些新的东西。如果你们对代码有任何意见或担忧,请明智地使用评论部分。敬请关注更多更新,直到那时再见。保持安全和快乐的编码!****