用深度学习检测假新闻
用 Keras 实现简单的 LSTM
图片来自 Pixabay 的 memyselfaneye
我一直想做一个涉及文本分类的小项目,并决定尝试一种我以前没有使用过的架构:长短期记忆(LSTM)。简而言之:LSTM 氏症是一种循环神经网络(RNN),能够长时间记忆信息(这是一种优于香草 RNN 的优势)。如果你想了解更多的细节:这里有一个关于 LSTM 建筑的精彩而详尽的解释。
好吧,让我们开始吧!
我在 Kaggle 上找到了一个真假新闻的数据集:真假新闻数据集。我试着在 Jupyter 笔记本上本地做这件事,但是一旦我到了训练部分,我的电脑几乎爆炸了——一个时期的 ETA 至少是 2 个小时。我把东西转移到一个 GPU 加速的 Google Colab 实例中,事情变得更加顺利。这里是查看笔记本的链接。
# load datasets into a panda's dataframe
real = pd.read_csv('data/True.csv')
fake = pd.read_csv('data/Fake.csv')
现在让我们看看数据是什么样子的。
“真实”数据集
“假新闻”数据集
real.head()fake.head()
我立即注意到的一件事是真实新闻文章中的“(路透社)”标签。事实证明,几乎所有的真实故事都来自路透社,几乎没有任何假新闻包含这个词。我想最终比较有单词和没有单词的模型。
real.loc[real.text.str.contains('Reuters')].count()/real.count()
> title 0.998179
> text 0.998179
> subject 0.998179
> date 0.998179fake.loc[fake.text.str.contains('Reuters')].count()/fake.count()
> title 0.013247
> text 0.013247
> subject 0.013247
> date 0.013247
现在,让我们给出数据标签,并将它们组合成一个数据集进行训练,然后对它们进行训练/测试拆分。
# Give labels to data before combining
fake['fake'] = 1
real['fake'] = 0
combined = pd.concat([fake, real])## train/test split the text data and labels
features = combined['text']
labels = combined['fake']X_train, X_test, y_train, y_test = train_test_split(features, labels, random_state = 42)
现在我们用 Keras 中的 Tokenizer 对象处理文本数据。我们不会删除停用词,因为每个词的上下文以及句子和段落的构成都很重要。我认为这两个班级的写作质量存在潜在的差异。路透社的记者居然有文字编辑!
# the model will remember only the top 2000 most common words
max_words = 2000
max_len = 400token = Tokenizer(num_words=max_words, lower=True, split=' ')
token.fit_on_texts(X_train.values)
sequences = token.texts_to_sequences(X_train.values)
train_sequences_padded = pad_sequences(sequences, maxlen=max_len)
现在让我们建立模型!
embed_dim = 50
lstm_out = 64
batch_size = 32model = Sequential()
model.add(Embedding(max_words, embed_dim, input_length = max_len))
model.add(LSTM(lstm_out))
model.add(Dense(256))
model.add(Activation('relu'))
model.add(Dropout(0.5))
model.add(Dense(1, name='out_layer'))
model.add(Activation('sigmoid'))model.compile(loss = 'binary_crossentropy', optimizer='adam',\
metrics = ['accuracy'])print(model.summary())
现在我们来训练模型。
model.fit(train_sequences_padded, y_train, batch_size=batch_size, epochs = 5, validation_split=0.2)
基于训练数据的 LSTM 模型训练进展
现在让我们评估一下测试/维持集。
test_sequences = token.texts_to_sequences(X_test)test_sequences_padded = pad_sequences(test_sequences,\
maxlen=max_len)
非常非常好。
绘制模型的准确性和损失表明,它可能仍然需要更多的训练,因为没有过度拟合的证据。
99%是一个很好的结果,但是,记住所有的真实新闻都有“路透社”在里面?假设它只是一个单词,我想看看从文本中删除它会如何影响模型的性能(如果有的话)。我认为在单词选择和编辑方面一定有很多其他潜在的模式,可能会使模型的分类变得容易。
从所有新闻文本中删除“Reuters”后,最终模型的测试集评估准确率为 98.5%。因此,其预测能力略有下降(0.6%的差异)。我还以为会更多。
获得这样一个几乎现成的好结果应该会让您更多地考虑底层数据。如果它好得令人难以置信,它很可能就是真的!路透社的新闻故事依赖于风格指南,并经过严格编辑,我不能说假新闻也是如此。这些潜在的模式可能允许模型从这个特定的数据集学习,但是它如何推广到从不同来源在野外发现的新闻呢?
我在 2019 年脸书上查看最多的假新闻文章上找到了一篇商业内幕文章。很难找到其中一些例子的全文。
对于第五个名为*“奥马尔与恐怖组织伊斯兰团体举行秘密筹款活动”的分享故事*,该模型预测其为真实。
对于标题为“*的#1 分享故事,特朗普的祖父是一名皮条客和逃税者;他的父亲是三 k 党成员,*模型预测它为假新闻 。
我还在 CNN 上抢到了当前的头条新闻,“ 特朗普将联邦社交距离准则延长至 4 月 30 日 ”,模型预测为真实。
结论
该模型似乎是训练和测试数据集上的一个非常强大的预测器,但是它可能不会在此之外进行很好的推广。当出现一个不符合设定的假新闻故事时,模型是 1 对 2。这个样本规模很小,我想尝试追踪更多数据集之外的假新闻,看看它的表现如何。我也想尝试更多的艺术模式(埃尔莫/伯特)。希望你喜欢阅读!
在 Luckin Coffee 的收益电话会议记录中发现欺诈
本文使用自然语言处理技术来检测受会计丑闻困扰的中国咖啡连锁店的欺诈行为。
Ashkan Forouzani 在 Unsplash 上的照片
2020 年初,Luckin Coffee 在首席执行官承认在公司 2019 年的盈利报告中夸大会计数字后,从纳斯达克证券交易所退市。
Luckin Coffee 曾被誉为星巴克在中国咖啡市场的最大竞争对手,被指控在 2019 年捏造销售收入。尽管丑闻花了一些时间才被曝光,但它启发我开始思考通过文字检测欺诈的可能性。
本文重点介绍了将自然语言处理技术应用于 2019 年第二季度和第三季度的 Luckin Coffee 收入电话。我们将努力寻找有价值的花絮并回答这些问题
我们能在管理层的言辞和语气中找到欺诈的暗示吗?
通过文本挖掘技术,我们是否也能快速有效地发现某个商业模式陷入困境或不可持续?
关于数据集
我通过 Luckin Coffee 的官网下载了它的收入通话记录。机器人流程自动化工具用于将 pdf 文本提取到 r。
本文中用于分析的 CSV 文件的快照
清理和浏览数据集
像任何数据科学项目一样,我们需要了解我们的数据集并清理它。由于这是一个相对较小的数据集,我只删除了常见的停用词,所以我们仍然有足够的数据用于分析。
删除停用词前后的字数
Luckin Coffee 的赚话费谁说的最多?
首先,我们来看一下 Luckin Coffee 财报电话会议中与会者的发言字数。正如预期的那样,首席财务官和首席执行官在电话会议上与观众分享了最多的内容。
在 Luckin Coffee 收入电话中发言字数排名前 10 位的参与者
想象每个参与者的极性
情感分析帮助我们提取一个人对某个主题的观点,无论是积极的还是消极的。在这一部分中,我们试图找出 Luckin Coffee 的收入电话中每个参与者的情绪。
下面的图表通过持续时间和频率显示了每个参与者的极性。消极词汇被分配较低的分数(消极分数),反之,积极词汇获得较高的极性分数。
请注意,下面的第二张图表显示,Luckin Coffee 的首席执行官、首席财务官和董事长在收入电话会议中使用了许多积极的词语。
Luckin Coffee 收入电话中每个人的极性。
咖啡还是茶?—分析 Luckin Coffee 收入电话中最常用的单词/短语
最流行的文本挖掘技术之一是找出特定单词在数据集中出现的频率。在本节中,我们将使用词频来分析 Luckin Coffee 的商业模式。
基于 Luckin Coffee 收入呼叫的二元条形图
根据上面的双字频率条形图,我们可以对该公司的业务模式做出一些假设:
- 咖啡和茶为主要产品 : Luckin Coffee 一直标榜自己是星巴克在中国咖啡市场的竞争对手。除了咖啡产品,该公司还积极尝试渗透到中国的茶叶市场。
- 注重赢得顾客的忠诚度:“保留率”和“营销费用”这两个词表明,Luckin coffee 正在花费大量的营销费用来赢得中国饮料市场份额。
- 向中国特定城市扩张:中国有一个城市等级体系,每个城市属于一个特定的等级。例如,北京和上海是一线城市。我们可以假设 Luckin Coffee 正在将其商店网点扩展到特定级别的城市。
- 利用合作模式获得更多客户:有趣的是,“合作模式”一词成为收入电话中最热门的双字母词之一。我们还可以假设 Luckin Coffee(计划)通过合作关系发展业务,以获得更多客户和/或扩大其商店的位置。
词频让我们了解一个主题的主题。接下来我们看单词网络图来看构成本题内容的单词。
词网络图:Luckin Coffee 的价值主张和通过合作模式增加的增长
下图显示了在收入电话中经常一起出现在一个句子中的单词。下图突出了三个主题。
词网络图——句内共现
- Luckin Coffee 的价值定位主要集中在以实惠/有效的价格销售,同时在便利的位置保持其质量
- 为了实现这一价值主张,Luckin Coffee 瞄准中国租金可能更低的低线城市是有意义的
- 在公司内部建立伙伴关系模式的目标是在不同的地点获得更多的客户
通过以上发现,我们可以怀疑 Luckin Coffee 的收入报告中捏造的销售数字可能是由于其与其他方的合作关系管理不善。
快速开设新店——分析最常用的情感词汇/短语
除了找出每个参与者在赚钱电话中的极性,我们还可以将单词标记为特定的情绪,然后进行单词计数。在我们的例子中,我们将查看 Luckin Coffee 的首席执行官(在捏造的销售调查中终止)和首席财务官的情绪词频。
总的来说,这位首席执行官在两次盈利电话中使用了“商店”一词约 25 次(在积极和预期类别中)。第二和第三个经常提到的词是‘伙伴关系’(约 6 次),和‘需求’(约 5 次)。注意第一个单词和第二个单词之间有很大的差距。这可能是一个信号,表明 Luckin Coffee 如此专注于其扩张计划,以至于该公司忽视了客户想要的产品吗?
情感词频柱状图——luck in Coffee 的 CEO
至于首席财务官和首席社会官,“商店”一词也被提到了近 40 次,负面和悲伤类别中的“较低”也被提到了约 15 次。这些发现可能表明,2019 年的大部分金融行动都是为了在中国扩张门店。
情感词频柱状图——luck in Coffee 的 CFO & CSO
接下来,我们还可以通过 CFO & CSO 所说的话来看看出现在“lower”前后的单词。
出现在“下级”前后的词— CFO 和 CSO
我们注意到“低”这个词与城市等级和租金相关。低线城市的人口规模和收入水平通常较低。因此,这些城市的租金也低于北京等一二线城市。这些发现表明,Luckin Coffee 的目标是在中国的低线城市开设更多门店。
自动售货机和中东咖啡市场——从盈利电话中提取关键词。
另一种流行的文本挖掘技术是通过数据科学的视角从文档中提取关键词。在我们的例子中,我使用udpipe
R 包中的 RAPID 和 PMI 函数从收入调用中获得关键字。
快速是指快速自动提取关键词。RAPID 算法试图通过分析单词的频率和共现来确定文本数据中的关键短语。
RAKE 方法确定的关键字条形图
PMI 指的是逐点互信息,寻找成对的词的搭配顺序。该算法将尝试识别比预期更频繁地同现的单词序列。
通过 PMI 方法识别的关键字条形图
RAKE 关键字提取方法产生类似于词频技术的结果。另一方面,PMI 方法提供了更多见解,包括:
- Luckin Coffee 与其他方有风险投资协议(也许是 Louis Dreyfus?)
- 除了打入中国的咖啡市场,Luckin Coffee 也在关注中东市场。
- Luckin Coffee 已经/可能计划通过自动售货机出售他们的饮料。
结论
简而言之,我们能够通过文本分析探索 Luckin Coffee 的商业模式。有几点可能暗示该公司存在欺诈行为。
首先,管理层极度关注供应方面——开设新店。虽然该公司解释了其需求战略——通过合作模式留住客户,但在财报电话会议上并没有过多提及“需求”、“客户偏好”等词。
第二,Luckin Coffee 盈利报告中捏造的销售数字可能是因为该公司对外部零售方的管理不善。自 2019 年年中/年底以来,Luckin Coffee 一直在中国日报开设新店。雷鸣般的扩张速度可能导致管理层失去了管理和与合作伙伴合作的能力。
最后,Luckin Coffee 计划渗透到中国的咖啡和茶市场。看看捏造的销售是否与其新推出的茶产品有关,这将是很有趣的。
用机器学习探测系外行星的可居住性
“宇宙是一个相当大的地方。如果只有我们,这似乎是对空间的极大浪费。”卡尔·萨甘
山姆拍摄的照片🐷 on Unsplash
我们大多数人都想知道在我们的星球之外有生命吗?对我们的祖先来说,我们似乎首先是孤独的,但当我们检查星星时,我们意识到这是一个相当大的宇宙。然后我们开始问地外文明是否存在,它们在哪里?我们把这个问题称为费米悖论。它陈述了缺乏地外文明证据和对其概率的各种高估计之间的矛盾。
但是,正如卡尔·萨根所说:“缺乏证据并不是不存在的证据。”所以我们正在寻找外星人在哪里,或者他们是否存在的问题。
系外行星研究的主要工作领域之一就是找到这个问题的答案。在不同的恒星系统中寻找可能适合居住的行星是系外行星研究的主要目标之一。到目前为止,我们已经发现了 60 颗可居住的系外行星,我们将继续寻找更多的系外行星。
照片由 Alazar Kassahun 在 Unsplash 上拍摄
所以,我决定开发一个机器学习项目来预测这些可居住的行星。通过进入这个项目,我提取了两个数据集:美国宇航局系外行星档案和 PHL 的可居住系外行星目录。
数据知识
因此,有两个数据集需要处理: Nasa 系外行星档案和 PL 数据,其中包含可居住性情况。我从美国宇航局获得的数据集是我的中心数据集,因为它有更多的恒星和行星的特征,例如;行星半径、恒星温度、轨道周期等等。我需要 PHL 的数据来使用可居住性功能。下图显示了目标特征的分布,这意味着可居住性。如您所见,我有一个不平衡的数据集,我将在下面的部分中处理它。
目标特征的分布。作者图片
方法学
本项目遵循的方法是:
- 预处理和数据合并
- 处理缺失数据
- 探索性数据分析
- 机器学习模型的数据准备
- 定义模型
- 评估和优化
天文数据集通常会有很多缺失值,我的情况也是如此。因此,我从清除这些丢失的值开始。
作者图片
这张图片显示了我丢失了多少价值。很明显,是很多。所以,我按照以下步骤来解决我的问题:
- 我删除了丢失数据超过 40%的列。
# remove columns with more than 40% missing data
def remove_missing(f):
count = len(planets[planets[f].isnull()])
if count/len(planets) > 0.4:
return 1
else:
return 0
missing_values = [x for x in planets.columns if remove_missing(x)]
planets = planets.drop(missing_values, axis=1)
- 我删除了具有十个以上唯一值的分类特征。
# remove categorical features with more than 10 unique values
cols = [x for x in planets.columns if x not in planets._get_numeric_data().columns]
for i in cols:
if(len(planets[i].unique()) > 10):
planets = planets.drop(i, axis=1)
- 对剩余分类特征的处理。
- 数值的迭代计算。
# IterativeImputer
# get only numeric values
numeric_values = planets[planets._get_numeric_data().columns]
imp = IterativeImputer(RandomForestRegressor(), max_iter=10, random_state=76)
numeric_values = pd.DataFrame(imp.fit_transform(numeric_values), columns=numeric_values.columns)
numeric_values.to_csv('Imputed Data.csv', index='rowid')
在下面的步骤之后,我得到了一个包含 131 个条目的干净数据集,并继续进行合并过程。
合并数据集
正如我之前所说的,我有两个项目数据集,所以我需要将它们结合起来,以便在机器学习模型中使用。除了可居住性,我的所有特征都在美国宇航局的系外行星档案中。因此,我把它从 PHL 数据集中拿了出来,放在中央数据集中。
#drop not-habitable planets
phl = phl[phl.P_HABITABLE != 0]#create habitable column for planets data with the help of phl #dataframe
#get names of planets
habitable_planets = phl.P_NAME.values
planets['habitable'] = planets['pl_name'].isin(habitable_planets
质量-温度-可居住性关系。作者图片
走向机器学习
我完成了清理和合并过程,但仍有工作要做。我应该做一些准备步骤,为机器学习模型准备数据。我仍然有这么多的功能,我不想从模型中得到过度拟合的结果。此外,我必须解决不平衡的问题。因此,我按照以下步骤编写了一些数据准备方法:
- 丢弃低相关性要素&为模型数据集选择高相关性要素。
- 经过一些研究,我决定将这些特征添加到模型的数据集中:行星质量、行星径向速度振幅[m/s]、平衡温度[K]、行星半径[地球半径]和轨道周期[天]。但是,由于缺失值问题,我只有行星半径和轨道周期。
- 标准化和对数变换。
- SMOTE —过采样。
#Selecting highly correlated features
unrelevant_features = corr_df[corr_df['habitable'] <= 0.09]to_drop = [column for column in unrelevant_features.index]
planets_c.drop(planets_c[to_drop[:97]], axis=1, inplace=True)planets_c[['pl_rade', 'pl_orbper']] = planets[['pl_rade', 'pl_orbper']]# log transformation to decrease the effect of the outliers
log_cols = ['gaia_plx', 'st_pm', 'gaia_pm', 'st_teff', 'pl_rade', 'pl_orbper']
planets_c[log_cols] = (planets_c[log_cols]+1).transform(np.log)
norm_cols = ['st_pmdec', 'gaia_pmdec']
planets_c[norm_cols] = preprocessing.normalize(planets_c[norm_cols])
嗯,我现在可以开始定义分类模型了。我从探索基本模型开始:KNN、逻辑回归、朴素贝叶斯、线性 SVC 和决策树。然后,集合模型就像:随机森林、AdaBoost、GradientBoosting 和 XGBoost。结果如下:
图片作者。
首先,行星半径和轨道周期特征不在模型数据集中。没有这些功能,我得到的最好的 F1 分数只有 54%,所以他们对结果做出了相当大的贡献。从特征重要度表也可以看出。
图片作者。
线性 SVC 是召回分数方面第二成功的模型。因此,我想比较他们的混淆矩阵:
作者图片。
最后的想法
- 像行星半径、轨道天数、恒星表面重力和恒星表面温度这样的特征对模型有重大影响。
- 机器学习算法在寻找可能的宜居行星方面做得很好,即使没有化学性质。
- XGBoost 在任务上真的很成功。这个模型预测了所有的系外行星,除了一个。
- 作为进一步的工作,我的目标是通过在学术论文上的 NLP 工作找到可居住性的相关特征。我还打算开发一个 flask 应用程序。
“以非常不同的方式,宇宙充满生命的可能性和我们完全孤独的相反可能性同样令人兴奋。不管怎样,对我来说,想更多地了解宇宙的欲望是不可抗拒的,我无法想象任何真正富有诗意的人会不同意。”理查德·道金斯
此外,如果你想了解更多,也可以看看我的 Github 简介!
用 CNN 检测白血病
机器学习
CNN 能可靠地识别癌细胞吗?
急性淋巴细胞白血病(ALL)是最常见的儿童癌症,也是 20 岁前癌症死亡的最常见原因。在 20 世纪 60 年代,所有人的存活率只有 10%,但诊断测试的进步和化疗的改进已经将发达国家的存活率提高到 90%。[ 1
研究人员正在尝试各种个性化的方法,主要是利用表观遗传学筛查和全基因组关联研究(GWAS)来确定潜在的抑制目标,以进一步提高存活率。[ 2 , 3 ]大约 80%的病例是儿童,但是,正如 Terwilliger 和 Abdul-Hay 所指出的,50 岁是所有发病率的另一个高峰,老年患者的长期缓解率低于儿童,约为 30-40%。[ 3
ALL 被描述为骨髓中淋巴细胞的增殖和分化。重要的细胞过程,如淋巴细胞分化的调节、细胞周期调节、生长因子和肿瘤抑制受体信号传导以及表观遗传修饰,被扰乱。此外,约三分之一的病例存在染色体易位。这可以通过将癌基因重新定位到活跃转录区域而导致癌基因的过度表达,或者通过将肿瘤抑制基因重新定位到基因组的非转录区域而导致肿瘤抑制基因的低表达。[ 1 , 3 ] ALL 通常是多克隆的,这进一步使治疗复杂化,因为许多亚群将可能对任何一种治疗产生抗性。 1
所有细胞形态
所有的都可以分成 3 个不同的亚型,这使得鉴别变得困难,即使对于有经验的从业者也是如此。L1 小而均一,圆形,无裂口,无明显的核仁或液泡。这些细胞最有可能成为正常的淋巴母细胞。L2 较大且不均匀,形状不规则,常开裂,并有明确的核仁和液泡。L3 具有 L1 的形状,但有明显的核仁和液泡。[ 4 , 5
照片由詹姆斯·格雷利尔在维基媒体上发布— CC BY-SA 3.0
数据收集
该数据由 10,000 多张单细胞显微术急性淋巴母细胞白血病和正常淋巴母细胞的图像组成,分类失衡约为 2:1,全部正常。在没有使用所有图像的情况下,有了足够的图像和计算资源,我决定对正的所有类进行下采样,以管理类不平衡。因此,用 4000 幅图像以 57:43 的类别不平衡完成了训练。
图像是存储为的 450x450 RGB 图像。bmp 文件,一种光栅图形位图,将图像存储为 2D 矩阵。
数据可以在这里找到。它来源于阿肯色医学科学大学(UAMS)对所有显微镜的研究。
探索性数据分析
这是我们组中的一些正常细胞。我们看到球形、未分裂的细胞,染色质均一,几乎没有液泡。
作者照片。
这是我们集合中一些 ALL 细胞。我们看到不规则形状的分裂细胞,有异质的染色质和多个核仁和液泡。
作者照片。
平均图像
查看每一类的平均图像,我们看到细胞内部有太多的变化,无法识别有意义的差异,但我们清楚地看到,所有细胞平均比正常细胞大得多。这并不奇怪,因为癌细胞的生长不受控制。
作者照片。
建模
我 用 Paul Breton 的这个 post 和对应的 GitHubrepo来指导 Sagemaker 使用 Keras。
我在 AWS Sagemaker 中使用了 Keras 框架,在 Model_Scripts 目录中的一个单独的 Python 脚本中指定了神经网络架构和编译超参数。训练是在 time 大型笔记本实例中完成的,允许在易处理的训练时间内完成数百个时期。
我采用了基于 CRISP-DM 过程的迭代方法来建模。预测多数类的虚拟分类器具有 57%的准确度。我创建了一个普通的模型,有一个 Conv2D 层和一个致密层,准确率为 68%,已经比虚拟模型好了。然后,我通过添加额外的 Conv2D 层和由 MaxPooling 层分隔的层块,创建了更大、更复杂的体系结构。
最复杂的模型在 3 层的 3 个块中有 9 个卷积,但这不是最成功的模型,因为它似乎过度拟合了我们的训练数据。很明显,深而窄的块比宽的块获得了更高的指标。最好的模型是一个 2x2x1x1 结构,总共有 6 个回旋。在 MaxPooling 和 Dense 图层之后添加了 MaxPooling 图层和 Batch Normalization 图层,以防止过度拟合,但最终模型中没有这些图层。
我尝试使用召回率作为模型选择的辅助指标,但是这将模型推至总是选择所有图像,并将模型精度推至虚拟分类器。因此,我决定放弃回忆,专注于准确性。由于召回率如此之高且牺牲了准确性,该模型作为一种工具将毫无用处,因为无论如何,所有图像都必须由人类医生进行检查,这就否定了该模型的益处。
最终网络架构
作者照片。
模型编译超参数
我使用二进制交叉熵作为损失函数,因为这是一个二进制分类问题,RMSprop 和 Adam 用于优化。学习率设置为 0.001,衰减为 0.0001。
模型部署
使用 AWS 端点部署了性能最佳的模型,以便从测试集中加载尚未看到的图像,从而生成预测。部署位于我的 GitHub 中模型训练下的 003_Modeling_AWS 笔记本中。
错误分类的图像
在这里,我们看到一个模型误归类为正常的图像,而它实际上是所有。该模型显然是对缺乏内部空泡和分裂以及致密染色质作出反应,以归类为正常。不规则的形状应该表明这是所有。
作者照片。
在这里,我们看到一个图像,该模型误归类为所有,而它实际上是正常的。该模型可能会对不规则的细胞轮廓以及内部较亮的不均一区域做出反应,这些区域表明存在空泡或未包装的染色质,从而将其归类为 ALL。这绝对是一个具有挑战性的细胞正确排序。
作者照片。
见解和建议
该模型达到了 84%的准确率,使其成为在新病例中识别 ALL 的有用工具。由于血液样本显微镜检查已经是所有人的默认诊断测试,该模型可以很容易地用于验证人类医生或标记该模型没有信心进行进一步审查的病例。即使对人类来说,诊断 ALL 也是困难的,因此拥有一个健壮、准确的验证模型可以提高诊断的速度和准确性。由于 ALL 是一种急性白血病,因此早期确诊尤为重要,如果不治疗,它可能在几周或几个月内死亡。
后续步骤
模型改进
这种模式有几个潜在的改进途径。我尝试使用 Adam optimizer,它为 RMSprop 计算的梯度增加了动量和偏差校正的感觉,并使用批量标准化来提高模型性能,尽管它迄今为止确实有助于建模。我还可以实现早期停止和模型检查点,通过允许模型在达到过度拟合阈值时停止训练来对抗过度拟合。我尝试了几个层次的辍学,定在 25%,但进一步的调查可能会产生更好的结果。
产品改进
模型的可解释性通常与模型的准确性同等重要,甚至更重要,尤其是对于医学诊断需求而言。在现实世界的应用中,医生能够看到为什么模型已经达到某个决定是非常重要的。为此,建立一个图像分割模型来识别和标记重要的特征,如图像中空洞、非球形细胞或切割边缘的存在和数量,可以大大提高模型的可用性。此外,部署模型并允许新图像的实时集成将使模型保持最新。
连接
这是这个项目的 GitHub repo。你可以在 LinkedIn 和 Twitter 上与我联系,或者访问我的网站获取更多文章。
来源
[1] S.P. Hunger 和 C.G. Mullighan,儿童急性淋巴细胞白血病。2015.新英格兰医学杂志 373(16):1541–1552。
[2] C.H. Pui,J.J. Yang,S.P. Hunger 等,儿童急性淋巴细胞白血病:通过合作取得进展。2015.临床肿瘤学 33(27):2938–2948。
[3] T. Terwilliger 和 M. Abdul-Hay,急性淋巴细胞白血病:综合综述和 2017 年更新。2017.血癌杂志 7:1–12。
[4] M.M. Amin,S. Kermani,a .塔莱比和 M.G. Oghli,使用 K-Means 聚类和支持向量机分类器识别显微图像中的急性淋巴细胞白血病细胞。2015.医学信号与传感器杂志 5(1):49–58。
[5] F. Scotti,外周血显微镜图像中急性白血病识别的自动形态学分析。2005.测量系统计算智能会议。
使用计算机视觉检测车牌
给定汽车的图像和视频,计算机视觉将被用来找出车牌的样子以及如何检测车牌。
来自 Unsplash 的 Damir Kopezhanov 的 Phtot
计算机视觉是一个不同于任何其他领域的数据科学领域。他们不是处理数据集,而是处理图像。与神经网络试图像人脑一样处理数据一样,计算机视觉试图以人类视觉的方式来查看、识别和处理图像。
在本文中,我们将检测计算机视觉最常用的案例之一,检测车牌。它们很明显,很容易辨认,这使得它们很容易被计算机拾取和识别。但是首先我们要让电脑知道是什么让车牌成为车牌。
级联分类
我们告诉电脑车牌是什么样子的方法是,我们给它几百个车牌样本,以及不是车牌图像的样本。然后在这些例子上训练一个分类器,如果输入图像包含牌照,它将输出 1,否则输出 0。
级联分类的不同分类器
级联分类被用作分类器,因为它由几个更简单的分类器(阶段)组成,这些分类器随后被应用于感兴趣的区域,直到在某个阶段候选被拒绝或者所有阶段都通过。这些简单的分类器检测车牌的边缘、车牌中的线条和周围的特征。如果在输入图像中不能检测到这些分类器中的一个或多个,它将拒绝该图像并声明没有牌照。但是如果可以找到所有这些特征,它会将图像分类为其中有牌照。
特征匹配
为了让您了解级联分类的作用,我将向您展示一个特征匹配的示例。特征匹配从两幅图像中找到相应的特征。
下面是一张汽车牌照和车尾的照片。特征匹配要做的是找到与汽车后部图像中的特征相对应的车牌特征。
特征匹配的输出
上面的图像是匹配两幅图像的特征的输出。这些线条显示了两幅图像中的共同特征。正如我们所见,几乎所有的线路都连接到汽车后面的牌照上。这基本上就是级联分类器的工作方式,以及它如何检测图像中的车牌。
结果呢
在我们对图像应用级联分类之后,如果检测到牌照,它将返回在图像中发现它的位置的 x,y 位置以及牌照的宽度和高度。现在我们已经有了图像中显示车牌位置的点,我们可以在图像上绘制一个围绕它的矩形。使用 OpenCV(一个计算机视觉库),它有一个功能,我们可以在给定的图像上绘制矩形,它所需要的只是应该绘制的点。
因此,从级联分类器输出的 x,y,宽度和高度,我们可以改变这个图像…
原象
o…
检测到牌照,现在它周围有一个红色框
但是有了这些点,我们可以做更多的应用。我们能做的实际上是模糊车牌。这在现实世界中经常使用,因为显示汽车的电视网络在没有他们的批准下不能合法地显示某人的车牌。所以他们模糊了车牌,这样就没人能看到了。类似于绘制矩形,OpenCv 有一个函数,给定一组点,它将在该位置模糊图像。
所以我们的原始图像变得模糊,现在看起来像这样…
牌照模糊后,就再也看不清楚了
检测视频中的车牌
为了理解我们如何做到这一点,我们必须了解什么真正构成了一个视频。视频本质上只是连续放置的帧,以感知某物在移动。你可以把它想象成一本动画书,当书被翻动时,图画看起来会移动,即使只是图像一次改变一点点。构成视频的这些帧只是被轻微改变的图像。因此,就像我们对上面的图像所做的那样,我们要做的就是对给定视频中的每一帧应用相同的分类器。如果该框架有一个牌照,一个红色的矩形将被放置在它的周围。
将要使用的视频是在高速公路上行驶的汽车。为了展示计算机视觉的更多应用,我们不仅要检测下面视频中的汽车牌照,还要放大牌照并显示在每个牌照被检测到的地方。
注意:不要指望分类器会提取视频中的每一个车牌。你会发现,当一辆车离得太远时,它就不会认出那个车牌,因为车牌的特征开始变得不太清楚,无法通过分类器。
视频中的计算机视觉
结论
计算机视觉不同于其他任何视觉。这是一个不断发展的领域,数据科学家和工程师正在寻找新的方法来创建有影响力的可视化。上面的例子是为了给那些不知道什么是计算机视觉的人一个介绍,并让他们了解计算机视觉的发展方向。希望这能激励你更多地了解这个迷人的领域,就像它激励我做这个项目一样。
如果你感兴趣,这个项目的代码可以在我的 GitHub 上找到:https://GitHub . com/zita 9999/License-Plates-and-Computer-Vision/tree/master
参考
[1] K .穆拉塔列夫,白色轿车,【https://unsplash.com/photos/3Gg-98LaCxE
[2] G .比亚尔基,黑色奔驰,【https://unsplash.com/s/photos/pennsilvania-licenseplates
[3]4k 都市生活,https://beautifulwashington.com/汽车驾驶放松视频,
[4] OpenCV,级联分类,https://docs . OpenCV . org/2.4/modules/obj detect/doc/Cascade _ class ification . html
利用迁移学习检测疟疾
使用机器学习和显微血液图像来检测疟疾
描述如何开发诊断疟疾的 ML 程序的视频。
弗朗切斯科·帕尔马和艾萨克·罗萨写的
在本文中,我们将首先描述疟疾是如何工作的,如何诊断这种疾病,以及它固有的问题。然后我们将讨论用于借助血液样本检测疟疾的 ML 模型及其性能结果。
疟疾是人类已知的最致命的寄生虫相关疾病之一。自从人类出现在地球上,它就一直存在,而且肯定会长期存在。
2018 年,有 2.28 亿人感染,405,000 人死亡,这是一个重大的健康问题。
非洲是所有疟疾病例的 94%(2018),但它也在中国南方流行,几乎存在于所有大陆。由于疟疾主要袭击非洲国家,遏制和有效抗击这种寄生虫变得更加困难。事实上,疟疾肆虐的发展中国家并不总是拥有适当的资源来降低其对疟疾的脆弱性。
据估计,受疟疾影响的国家每年损失 120 亿美元,这是由于许多公民在疟疾大爆发期间无法工作、高昂的医疗费用以及对旅游业的不利影响。加上大约 27 亿美元的人道主义援助,毫无疑问,疟疾对受影响国家的经济产生了巨大的负面影响。
疟疾,是什么?
疟疾实际上只是这种疾病的名称。它是由一种单细胞原生动物寄生虫引起的,这种寄生虫的属名是疟原虫。
疟原虫包括各种各样的寄生虫,大约有 200 种,但只有少数几种能污染人类。因为它们是寄生虫,所以它们利用几种宿主来进食和繁殖。
5 种疟原虫寄生虫能成功寄生人类并对人类有害,迟缓疟原虫、间日疟原虫、卵形疟原虫、三日疟原虫、诺氏疟原虫 (P 代表疟原虫)。虽然引用的所有 5 个物种都可能导致疟疾,但通常致命并导致严重疟疾的是弱毒疟原虫。
引起疟原虫的两种不同类型的疟疾,来源:https://microbenotes . com/differences-between-plasmodium-vivax-and-plasmodium-falciparum/
与其他类型的寄生虫相比,这些寄生虫的生命周期相当简单,因为它们只有两个宿主,即蚊子和人类。
这种寄生虫的生命始于蚊子的肠道,经过一个繁殖阶段后,它们转移到昆虫的唾液腺。当蚊子以人类为食吸血时,疟原虫进入了人类的血流中。感染后,它们首先进入肝脏并经历增殖期。一旦成熟并达到更高的数量,它们就会离开肝脏,进入红细胞。
此时,寄生虫将不断繁殖,直到身体能够有效地对抗感染。一些疟原虫将分化成有性卵样细胞,并在人类血液中自由流动,直到蚊子再次进食并吃掉它们。一旦再次进入蚊子的内脏,雄性卵样细胞将使雌性受精,循环可以再次开始。
疟原虫的生命周期,来源:https://sk.pinterest.com/pin/706220785288117948/
疟疾发烧通常发生在疟原虫大量冲出红细胞时,并引发免疫反应,如高烧、呕吐、恶心和头痛。由于许多红细胞被溶解,在某些情况下还会导致贫血,这种贫血会导致多种器官衰竭和代谢性酸中毒。
有效对抗寄生虫的最好方法在于预防胜于一切。这包括晚上睡觉时使用驱蚊剂和驱虫蚊帐。一些高风险地区也用杀虫剂熏制,以避免有太多的蚊子。
一旦感染,有几种药物存在,但这种药物必须非常迅速地给药,以避免对个体的严重伤害甚至死亡。
这种寄生虫的一个大问题,也可能是它仍然存在的主要原因之一,是它能够迅速进化并对它遇到的药物产生耐药性。随着蚊子对杀虫剂产生抗药性,抗击疟疾变得更加困难。此外,发展中国家的不卫生条件,尤其是撒哈拉以南非洲,是理想的蚊子滋生地,尤其是在雨季,昆虫有许多水坑产卵。
避免疟疾严重并发症的最有效方法是快速诊断。这样既能避免死亡,又能遏制寄生虫,以免感染更多人。
检测疟疾感染最常见的方法是进行显微镜血液分析。这不需要一套复杂的技能,但是,基本的医学知识是必不可少的。问题是,在发展中国家,适当的医疗材料和人员并不总是容易获得,使得这种诊断慢于预期,如果不是不存在的话。
另一个主要问题是,当资源可用时,有高估感染人数的趋势。许多研究表明,存在严重的过度诊断问题(某些农村卫生中心高达 98%的错误诊断(安哥拉,2012)。这导致疟疾治疗被大量滥用,因此可能导致疟疾药物短缺。此外,这种药物滥用降低了患者在真正生病时对药物的反应,并增强了疟原虫的抵抗力。最后,这加剧了进行血液微观分析所需的适当知识的缺乏。
尽管为抗击疟疾做出了许多努力,但资源的滥用仍然是一个主要问题
A .我如何帮助治疗疟疾?
我们已经看到,滥用资源是一个主要问题,但如何更好地投资以帮助防治疟疾?
A.我可能是答案,而且在很多方面。首先,使用人工智能和人工授精程序快速检测这种疾病可以通过快速诊断挽救无数生命。鉴于之前看到的数据,它不仅比人快,而且可能更准确。这种准确性将导致更好的药物管理,从而节省大量资金。这些节省下来的钱可以重新注入,更好地利用。
给红细胞拍照非常容易,只需要一台显微镜和一个适配环就可以给红细胞拍照。一旦拍摄了照片,就有可能简单地通过一个 ML 程序来运行它,这个程序被训练来识别被感染的细胞。
鉴于检测感染的方法相当简单,我们认为可以尝试使用 Giotto 开发一个疟疾检测程序,不涉及任何代码。重点是输入未分类的红细胞图像,让程序以令人满意的准确度进行分类。
Giotto 是一个机器学习平台,可以开发图像分类的 ML 程序,而不必编码。要更详细、一步一步地描述乔托,你可以阅读我们以前的博客文章。
无代码平台使用起来很简单,这可能会真正使人工智能民主化。不仅任何人都可以使用它,而且部署 docker 的可能性意味着只有一台计算机,没有 wifi,你可以用最简单的方式使用人工智能。这是一个关键点,因为许多高风险疟疾区非常偏远,因此没有像样的互联网连接。如果这行得通,农村社区就不必去最近的医疗中心了(记住,有时这很远)。重点不是取代人类的专业知识,但当没有其他选择时,这可能是一个答案。
正确训练程序的关键是拥有适当的数据。这意味着你需要有充分标记的每类文件夹来分析,以及每个文件夹中更多或更少的相同数量的图像(当然,当谈到图像分类时)。我们使用了由 27’558 幅红细胞图像组成的数据集,其中一半是寄生的,一半是正常的。
拥有正确标记的图像是首要的
为了处理这个数据集,我们首先必须把它上传到乔托。然后,我们必须选择适用于我们图像的数据增强技术。在这种情况下,应用了所有的方法,因为它们都不会改变图像的完整性。通过进行这种增强过程,我们通过向模型提供比初始集更多的数据来提高模型的性能。
所有的数据扩充过程都应用于我们的数据。
一旦完成,我们必须选择模型的所有特性,比如 resNet 数和历元数。我们的模型在 resNet 34 和 30 个历元的情况下表现最佳。
这个项目的训练时间相当长,因为数据集非常庞大;完成培训大约需要 3 个小时。
通过 20%的验证分割,我们的模型实现了 97.88%的准确率,没有一行代码。
这个精度是令人满意的,因为为程序选择的设置不是太高(resNet 34 和 30 历元)。已经用 10 个时期获得了非常相似的结果(约 96%)。
结论
尽管医学取得了令人印象深刻的创新,但这种寄生虫仍然在世界许多地方蓬勃发展,每年夺走数十万人的生命。找到对抗疟疾的新方法至关重要。这可以帮助数百万人,也可以促进高风险地区的经济发展。
97.88%的准确率是令人满意的,尤其是这是在仅仅训练了 3 个小时,完全没有使用代码的情况下实现的。在资源匮乏的地方,这比那些很少或根本没有受过适当分析培训的人更容易获得更好的结果。这样一个简单的应用程序可以直接部署在农村地区,允许人们在没有其他选择的情况下进行自我治疗。
我们模型的总结。
你可以自己试试这个程序:https://cloud.giotto.ai/ic/malaria密码:malaria123
来源和链接
用于检测疟疾的细胞图像
www.kaggle.com](https://www.kaggle.com/iarunava/cell-images-for-detecting-malaria) [## 乔托
停止编码。启动人工智能
www.giotto.ai](https://www.giotto.ai/) [## 安哥拉的疟疾过度诊断和抗疟药的过度消费:后果…
疟疾病例的过度诊断高达 85%。*大量滥用抗疟药物。*缺乏数据可靠性…
www.sciencedirect.com](https://www.sciencedirect.com/science/article/abs/pii/S0001706X16311251?via%3Dihub) [## 疟疾|语义学者
德国联邦各部的工人们强烈要求国家赔偿…
www.semanticscholar.org](https://www.semanticscholar.org/paper/Malaria-Greenwood-Bojang/2245f5204a16f1e4765ed239b54432c9c4a96764) [## 一个二级医疗保健中心对儿童疟疾的过度诊断和过度治疗…
疟疾的过度诊断和过度治疗是疟疾流行国家儿童的一个主要问题。这个…
journals.sagepub.com](https://journals.sagepub.com/doi/10.1177/0049475515622861) [## 瓦基索临床诊断的成年女性中实验室确诊的疟疾发病率低
谢尔盖·叶戈罗夫,1 罗纳德·m·加利旺戈,1 阿洛伊修斯·塞马甘达,2,3 摩西·穆万加,4 艾琳·韦松加,4 乔治·米罗,5…
www.ncbi.nlm.nih.gov](https://www.ncbi.nlm.nih.gov/pmc/articles/PMC5109652/) [## 疟疾概况介绍
疟疾是由疟原虫寄生虫引起的。寄生虫通过被感染女性的叮咬传播给人类…
www.who.int](https://www.who.int/news-room/fact-sheets/detail/malaria) [## 疟疾
恶性疟原虫][诺氏疟原虫][三日疟原虫][卵形疟原虫][间日疟原虫]血液…
www.cdc.gov](https://www.cdc.gov/dpdx/malaria/index.html)
利用人工智能和计算机视觉实时检测密集人群中的面具
迈向美好未来的一小步
这是从半夜醒来开始的,在极度困难的过程中,由于新冠肺炎·疫情病毒,封锁期很长。
一个周六的早上 5 点,我起床去买东西,看到一群人在附近的办公区踢足球。然后我想,为什么我们不能从远处发现谁在不戴面具的情况下走来走去。
然后我突然想到,等等……你可以!我可以试试。(有时候你忘了,你自己拥有什么技能。我们大多数人都会这样!😂)我带着兴奋的心情回家,设置好自己的深度学习环境。
我使用我的版本 DarkNet 运行 YOLOv3 模型进行场景检测,并快速旋转标准场景检测模型。然后,我开始从不同的公共数据集和存储库中,管理一个由屏蔽和未屏蔽图像组成的数据集。
DarkNet 的美妙之处在于,一旦你构建了它所有的 C 二进制文件和绑定,重新训练它最外层的迁移学习就相当容易了。因此,我得到了模型的权重,然后我必须对数据集进行注释,并开始在我的 GTX 1060 上用 CUDA 进行大约 10 个小时的训练。
我达到一个点,直到损失为 0.02,然后导出生成的权重。
对我的网络摄像头拍摄的照片进行第一次测试
这是第一个结果。
我在几种光照条件下运行它,看到结果在低光照环境下波动,所以我添加了一些直方图均衡技术。
直方图均衡化为现有图像增加并平衡了一定程度的对比度。结果相当好。
下一步是通过视频来运行它。现在,在当前的封锁情况下,我无法使用 IP 摄像头,所以我让我的室友指向并拍摄我(原谅我的短裤😅,这里太热了!)从窗口到街上。
第二个测试来自我手机拍摄的视频
一旦精度适合我,我意识到我需要更多的性能提升。所以我尝试了不同的方法。我需要优化分配给运行该作业的线程的内存量,以及每个节拍处理的帧的缓存。
因此,我没有使用 Python 脚本来运行这项工作,而是必须整体构建 DarkNet 的其他模块,并使用 CMake 来构建我的操作系统的 C 绑定,并将 DarkNet 添加到我的系统路径变量中。现在,我可以只使用 CLI 运行推理了😉
然后我开始在密集人群的视频上进行测试
使用该模型在视频上运行推理
在印度的人群中取得了惊人的效果
这是 YouTube 上运行项目演示的最终视频。
我达到了大约 40FPS,这对于视频处理来说足够好了。我真的很想运行网络摄像头,但遗憾的是,被隔离并没有给我在我的公寓里太多的空间来大规模测试一些东西。
这意味着我们现在可以在 IP 摄像机、无人机、公共场所的闭路电视和系统网络摄像头上运行这一功能。
理想的情况是将它部署在数据中心 GPU 上,如 Nvidia 2020 主题演讲中宣布的新 Nvidia V100 ,以获得惊人的性能和大规模的结果。
如果我们只是发现问题,我们可以建立很多东西,我觉得大多数问题只是每天出现。我们只需要在这方面有所创新。
#住宿之家#住宿安全
用一对一检测黑色素瘤
生物医学数据的机器学习
使用皮肤镜图像创建自动检测黑色素瘤的应用程序
L 在需要对离散值输出进行分类和预测的应用中,多重分类的逻辑回归是一种很有前途的方法。在之前题为“癌症中恶性肿瘤预测的逻辑回归”的文章中,我介绍了这个惊人的监督学习模型背后的一些基本概念,暗示了它在预测乳腺癌恶性肿瘤结果中的可能用途。
在这篇文章中,我希望展示一对一算法,它代表了逻辑回归的一个特殊实现,扩展到多个结果。我们将看到如何在 Python 3.7 中创建一个基于该算法的病理学信息学应用程序,以自动使用皮肤镜图像来检测黑色素瘤。不幸的是,由于数据集的限制,这种方法对于实例和特征之间的比例不均衡的任务来说并不是最佳的。重要的是:本练习的唯一目的是揭示将机器学习应用于皮肤病变图像的基本概念,并且仅用于实验目的,而非临床使用。
那么,为什么要使用一对一算法对皮肤癌图像进行分类呢?
这是我个人的观点,利用生物医学数据,尝试用最直接的方法来解决一个复杂的问题。如果这种方法导致“过于简单”,找到它的限制可以让我们在扩展它时有更多的控制。同时,一个简单的程序可以让我们发现它在现实中是多么强大。然后,永远不要低估逻辑回归:它可能会让你吃惊!
我第一次看到一对一应用是在 Coursera 的机器学习课程上,由 Andrew NG 教授[2]。课程的第三周“主要”是对 MNIST 数据集进行分类的练习,该数据集由 5000 张手写数字图像组成。Andrew NG 的课程基于 Octave/Matlab 代码,因此当我决定用 Python 实现我的逻辑回归函数时,我将它应用于 MNIST 数据集进行测试。测试的准确率为 89.5%,matthews 相关系数为 0.88(将训练集拆分为 4167 个图像,将测试集拆分为 833 个图像)。MNIST 图像具有 20X20 像素的分辨率,这意味着输入 400 个特征。手写数字是灰度的,每个数字位于单色背景的中心。MNIST 数据集的性质使逻辑回归方法更加简单,并解释了它在正确分类数字方面的成功。
所以我想,如果我把我的一对一代码应用到一个由更复杂的灰度图像组成的数据集,去掉所有多余的特征并保留每幅图像的最小特征集,会发生什么。在这个实验中,我使用了 PH2 ,这是一个 8 位 RGB 彩色皮肤镜图片的数据集,是在佩德罗·西斯潘诺医院(葡萄牙马托西尼奥斯)的皮肤科获得的。我得到的结果是惊人的,尽管考虑到它的性能有点令人失望,这就是我将在这篇文章中向你展示的,以及 ML 理论的一些基础知识(最低限度)。
1.Pedro Hispano 医院)数据集
黑色素瘤(皮肤癌)是世界上最致命的癌症之一。美国癌症协会将其列为 2019 年美国 7000 多人死亡的原因。它来自黑素细胞,黑素细胞是含有色素的皮肤细胞。紫外线照射被普遍认为是最重要的致病因素。通过皮肤镜分析区分黑素瘤病变和良性皮肤癌是一项基本任务。然而,这种分类问题在医学上的复杂性至今仍是争论的焦点。
2019 年,来自南非德班夸祖鲁-纳塔尔大学数学、统计和计算机科学学院的 Adekanmi A. Adeguin 和 Serestina Viriri 利用 2017 年国际生物医学成像研讨会(ISBI)和 PH2 的数据集,开发了一种基于深度学习的黑色素瘤检测系统[3]。所有 PH2 图像的原始分辨率大约为 768x560 像素。200 个图像数据集包括三种黑色素细胞病变:80 个普通痣(结果 0)、80 个非典型痣(结果 1)和 40 个黑色素瘤(结果 2)。
2.上传和显示数据集
我已经将 PH2 图像转换为 128X128 像素的分辨率。您可以下载这个数据集作为压缩的存档文件“ PH2_128X128.pickle.zip ”。此外,我还制作了同一个数据集的另一个版本,通过双变量分析过滤掉所有冗余的特征,(见第 4 段),你可以在这里找到: PH2_128X128_BIVA.pickle 。
在进行本文提出的实验之前,请按照超链接下载这两个文件。然后打开你的 Jupyter 笔记本,输入代码 1 ,导入所有必要的 Python 库:
代码 1:导入库。
代码 2 将实现 UploadDataset 函数来上传 PH2 档案。
代码 2:上传一个 PH2 数据集
使用 UploadDataset 指定您从此链接下载的档案文件名:
df, X, y = UploadDataset('PH2_128X128.pickle')
该函数将返回一个 Pandas Dataframe, X 和 y 向量,并将产生以下输出:
Dataset uploaded.
archive: PH2_128X128.pickle
num of examples: 200
num of features (X): 16384
y is the output vector
num of classes: 3
在上传数据集的过程中, UploadDataset 提供了一些关于存档结构的有用信息,如数据集中示例的数量(200)、X 中特征的数量、以及类/标签的数量(在本例中为 3)。浏览表 1 中总结的数据帧,了解其结构:
表 PH2 数据框架
dataframe 表示 PH2 数据集的基本组成部分(此处未提供关于图像的具体信息,例如组织学)。关于完整数据库的详细描述,请点击 PH2 网站的链接。它由 ID 列、要素列和输出列组成。feature 列包含 16384 个特征的 numpy 数组,对应于 128X128 像素的乘积。
如果我们想要可视化存储在档案中的 200 幅图像中的一幅,则代码 3 的显示功能代表一种可能的解决方案:
代码 3:显示 PH2 图像
我们所要做的就是以这种方式调用显示函数:
Display(df, 1)
其中 df 是上传的数据帧,第二个参数,在这种情况下,1 是图像的编号。显示器的输出如图 1 所示:
图 1:来自 PH2 数据集的图片之一。(图片来自https://www.fc.up.pt/addi/ph2%20database.html)
该函数显示图像及其相关结果,在本例中为 0(80 种常见痣中的一种)。与原始图像相比,该图像的分辨率大大降低。我尝试了几种分辨率(256X256,512X512,以及更低的像 20X20,我的结论是 128X128 是一个很好的折中。显示功能在 128X128 像素灰度图像中重塑 16384 个特征的 numpy 阵列。无论如何,相对于样本数量,该数据集的特征数量仍然太高,这将导致稀疏性问题。正如我们将在接下来的段落中看到的,我将展示如何解决这个问题。
3.正则化 Logistic 回归及其对决策边界的影响
我们已经展示了 PH2 数据集,并描述了访问其图像的代码;现在,我们需要引入一些关于逻辑回归正则化的新概念,我们将在这种情况下使用。显然,处理正则化的论点听起来可能跑题了,因为 PH2 数据集受“太多特征”的影响,而不是“很少特征”的问题,这是正则化的典型情况。然而,我认为对于逻辑回归极限的详尽解释,一个完整的关于这个主题的讨论是值得考虑的。
为什么要正则化逻辑回归?
在机器学习中,我们将数据分为训练集和测试集。训练集用于调整代表我们模型的假设 h 的参数;测试集用于评估我们的模型在未知的新例子上的表现,概括新数据。术语“一般化”指的是我们的假设适用于新出现的病例的程度。如果我们要创建一个可以对三种皮肤癌进行分类并预测新的癌症样本的应用程序,这就是我们想要的。当您准备数据集时,首先要做的是浏览一下关于要素的观测值数量,避免欠拟合/过拟合问题。
例如,一个典型的欠拟合问题是当您的假设 h 与数据趋势的映射很差时(可能是由于缺少特征)。您可以添加额外的特性( x1 和 x2 )来添加额外的高阶多项式项。图 2 解释了这一概念,以应用于两类皮肤癌的逻辑回归的可能实现为例。图 2A 示意了装配不足的问题:
图 2:欠拟合和过拟合问题。青色圆盘代表普通痣;紫色星星对应黑色素瘤。
增加额外的特征会导致更好的假设,如图 2B 所示。但是当添加了这些额外特性之后,我们不得不面对相反的问题时,问题就出现了:过度拟合。文献中描述的解决欠拟合问题的方法之一是正则化成本函数的所有θ。
等式 1:逻辑回归成本函数。
逻辑回归的成本函数(如等式 1 中所述)的特征在于假设 h 具有 sigmoid 函数,用于非凸性(如本文所述)。
正则化工作的机制包括惩罚我们必须添加到成本函数中的所有 θ ,以向特征添加额外的高阶多项式项,使它们变小。首先,我们希望消除膨胀成本函数的最后多项式项的影响,将它们减少到零。
等式 2:正则化的逻辑回归成本函数。
一种合适的方法是修改成本函数以收缩所有θ参数,因为我们不知道收缩哪个参数是必要的。在末尾添加一项(等式 2 中以黄色突出显示的新正则项)将具有收缩所有θ的效果。重要的是:不要惩罚θ0。 lambda 的作用是收缩θ,所以如果 lambda 极大,假设 h 就会欠拟合。
为了阐明整个正则化过程,让我们报告一个小测试。想象一下,从黑素瘤数据集的一系列图像中仅绘制两个特征(x1 和 x2)。这两个特征聚集在蓝色和橙色的两个同心环中。每个环代表属于普通痣(蓝色类= 0)的一组值,而橙色类= 1 的值对应于黑色素瘤。我们希望应用逻辑回归来预测新值将落在何处(例如,新的未知值将落在蓝色点组中还是橙色点组中)。此外,我们希望计算一个决策边界,将蓝色组与橙色组分开。(您可以通过此链接下载测试输入文件)。
图 3:测试。
看一下图 3:很明显,用一条直线将两类点分开是不可能的:这是一个典型的欠拟合问题(图 2A)。我们需要添加额外的特征来为我们的假设添加额外的高阶多项式项。这里提出的代码示例将通过一个 mapFeature 函数处理添加额外特征的测试,将两个特征向量(x1 和 x2)转换为一个 28 维的二次特征向量,比如 x1 + x2 + x1 + x2 + x1x2 + x1x2 …等等,其中输入 x1 和 x2 必须是相同的大小。那么,假设就会有这个形状:hθ(x)= g(θ0+θ1x1+θ2x 2+θ3x 1+θ4x 2+θ5x1x 2…)。训练新特征的多维向量将导致逻辑回归形成更复杂的决策边界(图 4)。
这个测试的 Python 代码被分成三个部分(代码 4 、代码 5 和代码 6 )。下载完测试数据后,按顺序复制并粘贴代码块。代码 4 包装了三个基本函数: Sigmoid 函数、 Cost 函数和 Gradient 。关于这三个功能的详细描述,我推荐读者阅读我的一篇文章,这篇文章致力于使用逻辑回归预测乳腺癌的恶性程度。
代码 4:正则化的逻辑回归函数
代码 5 绘制决策边界图的特征。该代码改编自由 Srikar 在其帖子中提出的 Python 源代码:
代码 5:映射特征
最后,代码 6 执行正则化测试并绘制决策边界(由 Srikar 重新调整):
代码 6:测试正则化和决策边界。
将代码 4 、 5 和 6 合并到同一个 Jupyter 笔记本中,运行整个练习:结果输出如下所示:
Running Regularized Logistic Regression...
Optimization terminated successfully.
Current function value: 0.394594
Iterations: 35
Function evaluations: 118
Gradient evaluations: 118
Accuracy %: 84.0
matthews_corrcoef: 0.6807791256663034
图 4:决策边界
准确率为 84%,马修斯相关系数为 0.68。这些结果随着不同的λ值而显著变化。
对于λ= 0.1,代码 6 还会生成一个数据集图,其中一条线代表决策边界
这里,我使用了 fmin_cg scipy 优化函数,它实现了用于线性方程组数值解的共轭梯度算法。共轭梯度法是作为迭代算法实现的。在这种情况下,使用优化算法来解决太大而不能由直接实现处理的稀疏系统是必要的。
4.维数灾难和双变量分析。
所提出形式的 PH2 数据集由 200 个观察值和 16384 个灰度像素特征组成。这个数字高得令人难以置信,因为它代表了一幅图像的总像素数。试图使用一系列图像的“所有像素”来训练逻辑回归是适得其反的。此外,特征的数量远远高于观测值,我们可能会遇到一个被称为“维数灾难”的问题。尽管如此,对于一个预测模型来说,200 次观察是非常少的。
“维数灾难”是理查德·e·贝尔曼(Richard E. Bellman)创造的一个表达式(也称为“p>>n 问题”,其中 p 代表预测值, n 代表观察值)。这个问题出现在分析高维空间中的数据时,空间的体积增长如此之快,以至于可用的数据变得稀疏。这种“稀疏”的后果之一是过拟合问题(图 2C)。当我们有太多的特征时,它就会发生。已学习的假设 h 可能很好地符合训练集,但是不能概括新的例子(例如,新的黑色素瘤或普通痣的分类)。
在因维数灾难而过度拟合的情况下,正则化没有帮助。相反,将数据减少到几个一致的特征可以解决问题。为此,我在这里使用了我上一篇文章中的双变量分析,来过滤掉多余的特征。
双变量分析是一种基于相关性的方法,它分析成对特征之间的关系。一般的假设是,高度相关的特征提供了我们想要消除的冗余信息,以避免预测偏差。以下代码改编自 AN6U5 ,用于相关矩阵的显示部分。上传 PH2 数据集后,从Chris Albon【4】重新改编的一段代码删除了所有相关性高于 0.9 的特征,保留了那些具有较低均值的特征。然后程序调用feature _ correlation _ matrix函数对矩阵进行可视化。该过程可以删除 16354 个冗余特征,仅保留 30 个。
代码 7:双变量分析。
图 5:删除冗余特征后的特征相关矩阵。
去除冗余特征后得到的相关矩阵如图 5 所示。该矩阵显示了 30 个相关性小于 0.9 的特征。每个要素都标有一个数字,该数字对应于原始 16384 要素数据集的索引。
5.一对多的实施
在关于癌症恶性预测的逻辑回归的文章中,我使用逻辑回归作为二元分类器,它能够将阳性类别与阴性类别(良性与恶性)分开。这里,我们需要扩展逻辑回归来解决多重分类问题。
PH2 数据集有三个结果:普通痣(结果 0)、非典型痣(结果 1)和黑色素瘤(结果 2)。一对一算法是逻辑回归的一种特殊实现,由三个不同的二元分类器组成。例如,如果我们从具有三个标签 0、1 和 2 的两个特征 x1 和 x2 收集值,在第一步中,算法将三个标签中的两个分配给负类,也就是说,标签 0 和 1 被分配给负类,而剩余的标签 2 被分配给正类。该算法前进到第二步,将负类分配给另一对标签(0 和 2),将正类分配给标签 1;在第三步,我们将把标签 1 和 2 标记为负,把标签 0 标记为正。所以我们有三个分类器,每个都被训练来识别三个标签中的一个。对于每个标签 i,**一对一训练逻辑回归分类器 hθ(x),以预测 y=1 的概率。每次计算对应于一系列θ值,这些值必须乘以向量*x。*最后,对于每个标签 *i,*该算法将挑选将 hθ(x) 最大化的唯一标签 i 。
图 6 将解释一对多过程:
图 6。OneVsAll 算法。图 6B :青色圆盘代表普通痣(结果 0),红色圆盘代表非典型痣(结果 1),紫色星星对应黑色素瘤(结果 2)。考虑来自两个特征 x1 和 x2 的值:该算法包括在三个步骤中实现的三个不同的二元分类器。第一步将标签 0 和 1 的值分配给负类,将标签 2 的值分配给正类。第二步将负类分配给另一对标签(0 和 2),将正类分配给标签 1。在第三步中,我们将把标签 1 和 2 标记为负,把标签 0 标记为正(图 6A 和 6C )。最后,对于每个标签 i ,,该算法将挑选将 hθ(x) 最大化的唯一标签 i 。
黑色素瘤检测的完整一对一算法包含在代码 8 中。在 Jupyter 笔记本单元格中复制、粘贴并运行代码。“main”部分表示代码的驱动部分,它由正则化逻辑回归成本函数和梯度函数组成。此外,代码还提供了两个功能,一对多的实现和测试结果的预测。
'''
MAIN
'''# Upload the dataset
df, X, y = UploadDataset('PH2_128X128_BIVA.pickle')# Split the dataset
X_train, y_train, X_test, y_test, indices, num_test = splitDataset(X, y)# Run oneVsAll
lmbda = np.float64(1e-4)
all_thetas = oneVsAll(X_train, y_train, lmbda)# Calc Accuracy
df_test_bench, pred_train, pred_test = CalcAccuracy(all_thetas, X_train, y_train, X_test, y_test, num_test)# Print the test results
df_test_bench
上传 PH2 数据集(双变量 30 特征版本)后, splitDataset() 函数将随机生成训练和测试数据集。然后 oneVsAll() 函数将在训练集上运行逻辑回归,但这里的一个关键函数是 *CalcAccuracy()。*该函数将计算训练和测试集的准确性。它将调用另一个名为 predictOneVsAll() 的函数,该函数将选取将 hθ(x)最大化的唯一标签 i ,使用以下 numpy 操作:
预测= np.argmax(sigmoid( np.dot(X,all_thetas。t)),axis=1)
最后, CalcAccuracy() ,将产生一个包含测试结果的 pandas dataframe,以及准确性和 matthews 相关分数。
代码 8:一对一对所有人
代码 8 产生的输出如下:
'''
-UPLOADING DATASET-
archive: PH2_128X128_BIVA.pickle
num of examples: 200
num of features (X): 30
y is the output vector
num of classes: 3
-SPLITTING DATASET-
random seed: 22549
# Training set: 160
# Test set: 40
-ONE VS ALL-
Optimization terminated successfully.
Current function value: 0.495204
Iterations: 67
Function evaluations: 251
Gradient evaluations: 251
Optimization terminated successfully.
Current function value: 0.526326
Iterations: 62
Function evaluations: 241
Gradient evaluations: 241
Optimization terminated successfully.
Current function value: 0.184121
Iterations: 215
Function evaluations: 884
Gradient evaluations: 884
-TRAINING ACCURACY-
Accuracy: 74.375000
matthews_corrcoef: 0.5928012927684577
-TEST ACCURACY-
Accuracy: 60.000000
matthews_corrcoef: 0.396701196586351
训练集由 160 幅图像组成,而测试集包含 40 幅图像。每次运行代码时,两个数据集的分割都是随机执行的。在这种情况下,训练准确率为 74%,matthews 相关分数为 0.59。对于测试的准确性,我们得到了 60 %, Matthews 相关分数为 0.40。也可以通过 df_test bench dataframe 获取测试结果:
包含测试结果的数据帧
代码 8 还包含一个名为*showthematheta(),的有用函数,它使用数据集的矢量 X 和 y ,所有标签的找到的θ矢量和在训练/测试期间计算的预测矢量,产生应用于特定图像的所有最大θ的输出。*例如,键入:
showTheMaxTheta(X, y, all_thetas , 145, pred_train)
该函数将显示图像 145 的最大θ值:
Real outcome: 1
Max Theta: 0.9213422724776613
Predicted category: 1
0
0 0.232627
1 0.921342
2 0.000085
这个图像的真实结果是 1,一个非典型痣,预测值是 1。这是因为标签 1 的最大θget 为 0.92,而标签 0 和标签 2 的最大θget 分别为 0.23 和 0.000085。
6.结论
一对一算法并不代表解决医学图像分类问题的最佳解决方案。这是一种基于多结果逻辑回归的算法,由于它被认为是一种广义线性模型,因此有许多限制。这意味着它的结果总是取决于输入和参数【4】的总和,而不是乘积/商。为 PH2 数据集计算的性能显示了低准确度和低的 matthews 相关分数(使用 matthews_corrcoef: 0.59 的训练准确度:74.4,使用 matthews_corrcoef: 0.40 的测试准确度:60.0)。这是一个典型的欠拟合问题,可能是由于数据集中缺少信息。尽管如此,该算法能够捕捉普通痣和恶性病变之间的差异,这是一个很好的观点,因为这意味着数据集下面有一种信息,一对一可以检索。我个人认为这个算法的性能可以通过增加图片的数量来提高。毫无疑问,200 次观察对于任何一种预测模型来说都是非常少的。特征的数量远远高于观测值,这导致了一个被称为“T2 维度诅咒”的问题。最小化特征是有用的,尤其是当我们处理图像的时候。双变量分析将 16384 个特征减少到 30 个。这可能意味着表征整个数据集的特征比我们想象的要少。“一对所有”限制的进化结果是神经网络的应用,它可以克服逻辑回归带来的许多问题,这将是我下一篇文章的论点。
参考资料:
- Andrew NG,机器学习| Coursera
- A.A. Adegun 和 S. Viriri,“基于深度学习的自动黑色素瘤检测系统”,载于 IEEE Access,第 8 卷,第 7160-7172 页,2020 年,doi:10.1109/Access。20207.686386866106
- 克里斯·阿尔邦(Chris Albon),用 Python 编写的机器学习食谱,O’Really,ISBN-13:978–1491989388。
- 机器学习常见问题解答:为什么逻辑回归被认为是线性模型?作者塞巴斯蒂安·拉什卡。
用 CNN 检测微控制器
点击时的对象检测
根据 Kaggle 竞赛数据检测微控制器的简单教程
像 TensorFlow 或 PyTorch 这样的 tandart 库没有提供任何简单的方法来训练你的自定义对象检测模型。很多时候你需要安装一个大的库作为 Detectron 2 或者 Tensorflow 物体检测 API。不要误解我的意思,这些库功能强大,但通常需要大量的检查、调优和处理数据。这就是为什么我想向您展示一种更简单有效的方法,通过调用 Rest API 和一点点击来训练您的检测器。
这种方法有一些优势:你不需要成为机器学习专家,你的数据都在一个地方。
资料组
对于本教程,我从 Kaggle 选择一个小数据集来检测由Gilbert Tanner[@ Medium]开发的微控制器。它包含大约 250 幅图像,包含四种类型的对象:
- Arduino Nano
- Heltec ESP32 Lora
- ESP8266
- 树莓 Pi 3
我们将通过 API 上传 Ximilar 平台上的数据(带边框的图片)。边界框包含 4 个坐标,并定义微控制器的确切位置(矩形)。我们也可以通过 app.ximilar.com 拖放图像,并通过绘制手动创建边界框。
创建任务和标签
在我们上传数据之前,我们需要通过应用程序定义我们的神经网络模型。我们将创建任务和 4 个与该任务相关联的标签。
创建带有一些标签的新任务。作者图片
选项 A:通过脚本上传数据
如果您不想手动创建所有的边界框,您可以通过运行以下脚本来上传它们。只需更改标签 id 并从下载的数据集文件夹中运行该脚本。
选项 B:用绘图框拖动&放置
用前端绘制边界框。作者图片
火车
上传所有数据后,我们进入微控制器任务页面,点击 训练 按钮。培训可能需要 30 分钟到几个小时。想出去走走也可以注销应用:)。这真的需要一些时间,因为用于对象检测的神经网络是在我们的服务器上自动训练的。
如果你想了解所有这些背后的神经网络架构,你可以查看 Libor 的帖子。
检查结果
训练已经完成,现在我们可以在一些图像上测试它。同样,我们有两个使用 API 或 app 来获取结果的选项。
检查训练好的模型。作者图片
在我们的任务定义中,我们可以看到我们的模型用 IoU 0.75 实现了 mAP 0.85。这是一个不坏的结果!什么是地图度量?解释在另一篇文章中,所以你可以在这里阅读更多。简单地说,数字越高,结果越好。如果我们转到训练模型的细节,我们可以查看每个标签的地图。我们可以看到数据集很平衡(每个标签有图像,每个标签有对象)。
您可以使用 Python SDK 客户端(这是一个 REST/JSON 包装器库)连接到 API,并获得经过训练的检测模型的结果:
训练模型的技巧
这只是我们的第一个训练模型,所以结果不是最好的。我们可以通过上传更多的图片和重新训练模型来改善它。如果是这样,应用程序将训练一个新模型,而不删除旧模型。如果你想对你的型号进行比较或 A/B 测试,这是很好的选择。
你可以玩其他的选择。您可以编辑高级选项来控制图像分辨率和图像增强技术。图像增强是一种改变(稍微或更积极地)输入图像以创建更大数据集的技术,因此您的模型将在更多图像上更好地泛化。
您还可以上传图像并将它们标记为测试,这样您的模型将始终在这些标记的图像上评估结果。这些图像在训练过程中是看不到的,因此您的测试数据集独立于您的训练数据集,并且该数据集的地图编号更加可靠。
最后的话
目标检测或目标识别只是机器视觉领域中许多常见问题之一。它可以用于电子商务中检测时尚服装,用于医疗保健中检测肿瘤组织,用于汽车油漆划痕的保险检测,用于检测免费停车位,等等。
使用数据科学检测含糊说唱
实践教程
使用数据科学建立一个模型,客观地将说唱歌手归类为咕哝者。
资料来源:pexels.com
警告:本文引用的说唱歌词可能包含露骨的语言。
介绍
了解我的人都知道,我花了很多时间处理数据和听说唱音乐。自从在小学收到我的第一张 cd“大威利风格”的威尔·史密斯,我几乎每天都要听说唱几个小时。从小学到现在,我获得了包括数据和统计在内的许多领域的知识和经验,当然说唱的世界也在不断发展。在嘻哈音乐的近期历史中,出现了一个被称为“咕哝说唱”的新流派。
城市词典将咕哝说唱定义为“一种听起来像中风患者试图发表演讲的音乐形式;往往无法理解,不合逻辑。”。在我看来,mumble rap 的一个很好的例子是 Playboi Carti 的@ MEH ,其中 YouTube 的顶部评论是*“听起来不错,等不及英文版了。”。然而,并不是每个例子都如此清晰,一些说唱歌手根本不想与“咕哝”这个词联系在一起。那么,谁来决定哪些说唱歌手符合成为咕哝说唱歌手的标准呢?因为甚至维基百科条目也将其描述为“定义宽松”,所以我决定打开我的数据工具箱来获得一个更客观的指标,看看你最喜欢的说唱歌手喃喃自语了多少。*
如何测试曼波
我测试曼波的想法很简单:
- 选一首歌
- 把它输入语音到文本的转换器
- 将生成的文本与实际歌词进行比较
当然,和任何软件项目一样,事情并不像计划的那样顺利。我大约一年前开始从事这个项目,但在进行了一些初步测试后,语音到文本转换器(Google API)似乎真的很难适应背景中的节拍、乐器和其他声音。糟糕的结果和一大堆其他项目的想法结合在一起,让我决定放弃这个项目。
快进到 2020 年初,我在 Reddit 上看到一个帖子,有人创建了一个在线工具来从歌曲中提取人声。由于这是丢失的关键,我再次对完成这个项目抱有希望。确定咕哝量的基本概念保持不变:
项目设置
除了这次我会先用工具提取人声。
现在让我们更详细地了解一下我是如何获得数据并进行分析的。
获取数据
我在收集数据时遇到了各种各样的障碍。最初的想法很简单:下载歌曲,去掉人声,然后输入 API。然而,我很快发现,尤其是在说唱音乐的情况下,一整首歌往往是录音艺术家发音的糟糕表现。这主要是因为:
- 合唱或挂钩占据了歌曲的大部分,不应该算作说唱
- 大多数说唱歌曲都有其他艺术家的诗句
这意味着样本应该限于诗句。对于每首曲目,将使用一段歌词。因此,我不得不修剪所有的歌曲,并选择相应的歌词部分。总而言之,这个过程是这样的:
为了获得音轨,我写了一个简单的机器人,但是选择正确的诗句和复制粘贴相应的歌词是一项繁琐的手工工作。由于手动部分花费了大量的时间,我不得不限制我的样本。我采用了以下方法:
- 在网上搜索“咕哝说唱歌手
- 选择前 15 名(受欢迎程度,而非质量指标)
- 在 Spotify 上搜索艺术家时,选择前 5 首歌曲结果
- (经典说唱重复)
这导致了 150 个轨道(15×5×2)。
当然,更多的说唱歌手和每位歌手的歌曲会产生更好的结果,但正如之前所说,数据收集是一项非常劳动密集型的任务,幸运的是,结果将显示大多数说唱歌手在不同的歌曲中相当一致。
一路走来,我意识到随着时间的推移,说唱音乐可能也变得越来越难以理解,因为俚语越来越多(例如“让我兴奋不已”)。所以我又添加了 30 首来自 Complex 的*“自 1979 年以来每年最好的说唱歌曲”。*此列表包含 30 多首曲目,但由于其中一些曲目与样本中已有的曲目重叠,因此只产生了 30 首新曲目,总共有 180 首曲目。我在 Kaggle 上分享了完整的表格。
在这里,您可以找到数据集中所有艺术家的概述和一些关键数字。
敲门者
按类别/类型选择所有艺术家。
轨道长度
按年份
准备数据
预处理
在开始预处理之前,我添加了一个额外的——虚构的——说唱歌手,我命名为“Lil Controlla”。“Lil Controlla”将作为一个控制组,到目前为止只发布了两首歌曲:
- OneHunnid (API 生成的歌词与实际歌词相同)
- 不匹配(API 生成的歌词与实际歌词完全不匹配)
“Lil Controlla”将帮助我仔细检查模型的各种参数。
人工智能生成了虚构说唱歌手 Lil Controlla 的图片。(来源:https://thispersondoesnotexist.com/)
对于预处理,对原始和 API 生成的歌词都应用了以下步骤:
- 删除所有标点符号
- 全部小写
- 删除 Genius.com 不需要的添加,如“[第 1 节]”
- 将俚语转换成英语(lil -> little,em -> them,…)
- 将数字转换成单词(21 个野人-> 21 个野人)
堵塞物
词干化是自然语言处理中的一种常用方法,用于将单词简化为词干,即词根形式的基础。例如,单词“ball”、“balling”、“baller”、“ballers”都将被简化为单词“ball”。对于这种分析,原始的 API 生成的歌词都被词干化。这是为了给语音到文本 API 更多的宽容。如果原来的歌词是“ballers”,但 API 捕捉到了“ballers”,人们可能会认为它不应该因此受到惩罚,因为你很容易就能从听音乐中分辨出来。通常,单词将被词干化为英语词典中没有的新单词,但这应该不是问题,因为 API 和原始变体都将被词干化为相同的基础。
在这里你可以找到预处理和词干化前后的一段诗的例子。这是来自 Genius.com 的版本。
预处理前&炮泥:富小子—塞走
你联系不到我(什么?)太空跑车像 E.T. (E.T .)它是插头 tryna 打电话给我(skrrt,skrrt)我在清晨捕捉(插头)哦,在波浪上像一个 durag (durag) Pussy nigga 呼叫他的 boo back (pussy)插头走,古驰在我的鞋架上(古驰)在房子里走,炉子在哪里?直到我跑进塞子(直到我跑进)直到我跑进烂泥(到烂泥)我跑进了一些架子,我跑进了你的女孩(对你的女孩)为什么塞子向我示爱?(向我展示我的爱)我从一个配音演员(嗯?)
预处理后的&炮泥:富小子—塞走
你够不到我什么样的空间妙招像 et et it’ the plug tryna 叫我 skrrt skrrt 我在清晨醒来像 durag durag pussi nigga 叫你嗨 boo back pussi plug 走 gucci 在我的鞋架上 gucci 走在房子里炉子在那里打着转直到我碰到塞子直到我碰到直到我碰到泥巴 我做的泥跑进一些机架我做的跑进你的女孩’到你的女孩,而插头显示我的爱显示我的爱我做了从一个配音嗯
模糊分析
现在数据已经准备好了,是时候进行实际分析了。对技术方面不感兴趣的可以跳过这部分,直接看结果。
从这一部分开始,我与我的朋友 Frederik Caenepeel 博士一起工作,他是一位数学家,对编码、数据和 hip hop 有着共同的兴趣。在一次我们用披萨、嘻哈和啤酒进行编码的会议上,我告诉了他这个想法,经过头脑风暴,我们决定一起解决这个问题。弗雷德里克也应该为上述单调乏味的工作得到赞扬。
为了确定原始歌词和语音到文本版本之间的相似性,我们使用了不同度量和影响这些度量的因素的组合。
达默劳-莱文斯坦距离
第一个,也是最明显的,我们用来比较原始歌词和计算机生成歌词的算法是 Damerau-Levenshtein 距离。该算法的原理非常简单,因为它归结为计算使字符串 A 与字符串 b 相同所需的操作次数。该算法的出发点是有三种可能的方法来操作文本:
- 插入
- 删除
- 代替
Cardi B 的《我喜欢》以“现在我喜欢美元,我喜欢钻石”开头。然而转录"美元"作为达拉斯。使用 Damerau-Levenshtein,我们计算两种操纵:
第一步:替换(O → A)
第二步:删除
使用这种算法为每个诗句生成一个分数,分配相似性的定量描述。在应用这个算法之前,我们使用 Python 的 NLTK 删除了停用词。你可以在这里找到更多关于这个算法的信息。
探测法
虽然 Damerau-Levenshtein 对于许多 NLP 项目来说已经足够了,但是这个特殊的案例也可以使用不同的方法。NLP 项目主要关注拼写或意义,而在这种情况下,更多的是语音理解。目的是听你是否能听懂说唱歌手的话,而不一定是你抓住了这个词的确切意思或拼写。让我用一个例子来说明这一点:如果一个说唱歌手说单词“nice ”,而 API 将其捕获为“guys ”,则没有一个字母重叠。然而,从语音的角度来看,这两个词非常相似。出于这个原因,我们决定增加一层分析,通过声音来比较单词。
SoundEx 是一种常用的语音算法,通过声音来索引单词。维基百科将该算法描述为:
- 保留名字的第一个字母,去掉所有其他出现的 a,e,I,o,u,y,h,w。
- 用数字代替辅音如下(首字母后):
b,f,p,v → 1 / c,g,j,k,q,s,x,z → 2 / d,t → 3/ l → 4 / m,n → 5 / r → 6 - 如果原姓名中有两个或两个以上同号字母相邻(步骤 1 之前),只保留首字母;同样,由“h”或“w”分隔的具有相同数字的两个字母被编码为单个数字,而由元音分隔的这种字母被编码两次。这条规则也适用于第一个字母。
- 如果单词中的字母太少,无法分配三个数字,则添加零,直到有三个数字。如果你有四个或更多的数字,只保留前三个。
这个项目的问题是,API 不一定会抓取每个单词,这意味着 API 生成的文本几乎总是比原始歌词短。因此,不能简单地使用 SoundEx 进行一对一的单词分析。为了克服这个问题,我生成了两个 SoundEx 列表:一个用于 API 文本,一个用于原始歌词。从后者中减去前者,剩下的元素就是那些没有被捕获的元素。尽管这种方法并不完美(考虑到不同地方相似的发音单词可能会导致冲突),但它确实很好地表明了使用语音作为度量标准的计算机生成的歌词的性能。
振幅
我们使用的第三个也是最后一个参数意外出现。正如数据收集中所描述的,这些歌曲是从 YouTube 上下载的,然后用在线工具进行了修整。该工具以波形音频格式(或简单地。wav)。事实证明,不同歌曲的质量有相当大的差异。虽然大多数曲目都是高质量的,但一些离群值的音频质量确实很差。将这些负面的异常值输入 API 会导致歌词的转录性能非常差。
对于人耳来说,并不总是容易听到差异,但通过可视化振幅,它变得非常清楚。基本思想是,较高的振幅导致较高的“音量”或响度。
这里你可以看到两个振幅变化很大的音轨的例子。
这种振幅差异的原因实际上很容易解释。记住,所有的歌曲都是从 YouTube 上下载的,音频质量是由上传者设定的。由于 YouTube 是一个相对现代的现象,本样本中的许多曲目来自 YouTube 出现之前的时代。与拥有唱片公司的现代艺术家上传尽可能高质量的歌曲不同,前几代人没有任何 YouTube 频道。他们的歌曲经常出现在 YouTube 上的唯一方式是由一些粉丝自己上传,通常是从 CD 上撕下来的。结果,轨道越老,质量越差的可能性越高,这表现在低振幅中。
为了用个位数表示质量,我用了功率,也就是每秒的能量。绘制每个时间段的平均功率时,您可以清楚地看到一段时间内的趋势。
不考虑 1975 年至 1980 年,其中只包含一个轨道,你可以看到质量大大提高,从 1995 年以后。尽管我们花费了大量的时间和精力来准备所有的曲目,但我们决定根据特定的标准放弃所有的曲目,因为糟糕的质量对转录性能的影响太大了。
我们提出的标准是:
- 仅 2000 年以后发行的曲目(与振幅密切相关)
- 追踪能量(振幅)至少为 50(去除异常值)
- 没有复杂的年度跟踪(随着时间的推移,我们决定放弃 2000 年的阈值)
- 仅剩余 3 首或更多曲目的艺术家
经过这一截,新的艺术家选择现在看起来像这样:
艺术家的最终选择。
组合参数
为了组合参数,我们考虑了许多不同的选项,包括更多的参数,如同一说唱歌手的方差、音轨长度、每秒字数、词汇丰富度等等。然而,考虑到这个(个人)项目的规模,不想过度设计,以及两个参数的满意结果,我们决定将其简化为一个非常简单的公式。
Mumble 得分= (DamLev 距离+ Soundex 得分)/ 2 *
*使用振幅作为先验标准。
使用这个公式,我们获得了每个音轨的“模糊分数”,范围从 0 到 1,解释如下:
0:非常差的分数,曲目除了喃喃自语什么都没有。
1:满分,歌词都是完全可以理解的。
结果
现在方法已经过去了,让我们来看看结果吧!
在这个柱状图中,我们可以看到所有说唱歌手的概况和他们的平均分数(分数越高,意味着咕哝越少)。颜色编码用于识别维基百科(见简介)中提到的咕哝说唱歌手。这张图表证实了这一假设,并清楚地表明所谓的咕哝说唱歌手的歌词平均来说更难用语音到文本分析来转录。但是让我们更深入地了解一些细节。
说唱歌手的结果
在光谱的低端,我们可以找到喃喃自语。那些是得分最低的艺术家。同样,低分数意味着语音到文本算法很难将他们所说/敲击的单词与实际歌词匹配。Young Thug,Gunna 和 Playboi Carti 在底部,这符合预期,因为他们有时被认为是 mumble rap 的“海报男孩”。我个人也不觉得奇怪。如果你自己听了他们的一些曲目,试着自己转录一下,你就会明白低分从何而来。
当我们看到最高分时,这些名字也并不令人惊讶。德瑞医生、J·科尔斯、纳斯和德雷克都表达得很好,很容易理解。看到 J .科尔在顶端是特别有趣的,因为他是一个众所周知的含糊说唱评论家。
在中间,我们可以找到一些说唱歌手,他们被“误标”为含糊不清的说唱歌手或非含糊不清的说唱歌手。基本上,他们是媒体给他们贴上的标签与数据不完全相符的艺术家。例如,21 岁的萨维奇经常被归类为含糊不清的说唱歌手,但这个实验表明,他实际上表达得相当好。另一方面,像李尔·韦恩这样的人似乎表现不如预期。然而,0.5 分左右的分数应该被轻松地解释为样本仍然很小,并且还有许多其他变量在起作用。对结果的主要关注点应该放在极端情况上:最含糊的和最清晰的。
说唱歌手的可变性
鉴于每位艺术家的样本很少,研究他们得分的可变性就显得尤为重要。每个说唱歌手的标准差(更容易解释)是这样的。
简单来说,你可以说标准差越低,mumble 得分越适合作为说唱技巧的代表。
按类型分类的结果
在这个项目的开始,我使用维基百科作为一个来源来寻找哪些说唱歌手被贴上了含糊不清的说唱歌手的标签。使用这种分类,我们可以比较咕哝组和非咕哝组的平均分数:
这种差异是显而易见的,因为不咕哝或“经典”说唱歌手的平均表现明显高于咕哝者,证实了这一假设。
跟踪结果
最后,我们可以看看“微观层面”,实际上看到模型在最佳和最差赛道上的表现。先说其中一首最好的(也是个人最喜欢的)J·科尔的《无角色 Modelz》(评分 0.86)。
j·科尔——没有榜样
作为一个低评分曲目的例子,我选择了 Playboi Carti 的“@ MEH”和臭名昭著的 YouTube 评论*“听起来不错,等不及英文版了。”*(得分 0.09)。
Playboi Carti — @MEH
最后,我想展示一个“标签错误”的例子。换句话说,一首歌获得的分数远低于/高于你听自己演唱时的预期。这是 DMX 的经典之作《X Gon’ Give It To Ya》。
DMX——X 会给你的
当听我们刮来的版本和从中移除乐器的版本时,我能够找到 API 性能差的原因之一;所有露骨的词都被审查了,这在音频中创造了大量的词间隙。看起来 API 在努力解决这个问题。此外,轨道的振幅也很低,这导致了较差的分数。
结论
当查看艺术家的结果时,我们可以将含糊或不含糊的标签归因于一些具有一定程度的信心的说唱歌手。例如,J·科尔显然处于正确的位置,与咕哝说唱保持距离,因为他的分数不仅很高,而且表现出一致性。其他作词人如纳斯、肯德里克·拉马尔和阿姆也不负盛名。在“口齿伶俐”的说唱歌手中,我们也可以看到像德瑞医生、Jay-Z、坎耶·韦斯特和德雷克这样的大牌。
另一方面,预期的咕哝者名不虚传,如 Playboi Carti,Gunna,Young Thug 和 Lil Pump。所以从现在开始,如果你听他们的音乐,却听不懂他们在说什么,要知道你并不孤单。从这一点上说,不仅仅是你,一个为理解人类声音而构建的计算机算法也和你一样在挣扎。
从整体上评价这个模型,我很高兴地说它表现得相当好。这些结果都符合你的预期,或者当你评价自己是一个“含糊不清”的人时,你会看到什么。我也对谷歌 API 的质量感到惊讶,即使它设法抓取了许多含糊不清的音轨,并正确转录了相当大的一部分。我们可以得出结论,该模型能够在含糊说唱和正常或“经典”说唱之间做出明智的区分。我甚至自信地说,60%的时候,它都有效…每次都有效!
最后,尽管整体表现良好,但仍有很大的改进空间。例如,像 DMX 和李尔·韦恩这样的说唱歌手得分远低于人们的预期。当考虑更多因素时(如露骨的语言或俚语),分数可能会更准确。API 似乎也在速度上挣扎,这在阿姆的《哥斯拉》中表现得较低。这给我们带来了一些可以在“进一步研究”下进行改进的列表。
进一步研究
尽管我和我的朋友在这个项目上花了大量的时间,但仍然有巨大的改进空间。在这里,我列出了一些可以改进或可以进一步探索的东西。
更多数据
这可能是最重要的一条。在目前的项目中,我们每个艺术家只有大约 5 到 8 首歌曲,这是非常低的。由于提取、整理、转换和转录音频的任务非常耗时,我们受到资源的限制,无法进行更深入的研究。将每个艺术家的曲目数量增加到至少 20 首应该会给出更可靠的结果。其次,总体上包括更多的艺术家也是不错的。我们试图尽可能客观地选择“经典”说唱歌手(基于谷歌搜索结果),但我们知道很多读者会不同意,因为他们最喜欢的说唱歌手不在名单中,而他们不喜欢的艺术家在名单中。总之,艺术家人均时间和艺术家总数都应该增加。
更高的数据质量
除了数据量,质量也可以提高。不幸的是,由于振幅太低,我们不得不移除许多音轨。YouTube 上的音频质量差别很大。理想情况下,应该从更好的来源抓取音轨,以保证所有音轨的高质量和同等质量。
重新思考公式
用于计算 mumble 分数的公式目前非常简单。我们认为可以通过增加一些参数来改善。比如,露骨的语言起了作用。有些曲目中的脏话被删掉了。因此,虽然这些词被写在原始歌词中,但它们永远不会被 API 拾取。另一个因素可能是每秒钟词汇和字数的丰富程度。想象一下,我们用了 Lil Pump 著名的“古驰帮”,与其他曲目相比,这是不公平的。如果 API 能够正确地选择它,那么对于相同的文本/单词,他的分数将会提高数倍。相反,如果 API 会错过它,他将被惩罚多次。应该考虑到词汇量的更大/更小的变化和每秒更高/更低的单词速率。
创建 Kaggle 笔记本
在写这篇文章的时候,我很快意识到这可能会变成一篇很长的阅读。正如你在我的其他帖子中看到的,我通常倾向于解释我的分析中的每一步,使读者能够完全复制这个过程。为了不使它太长,我没有详细介绍每一个步骤。因为我的代码中有 API 证书,所以我也没有使用公共笔记本(例如使用 Kaggle)。这样做将使其他人更容易在项目上合作,用更多的数据扩展它或改进分析。如前所述,我上传了数据,你可以在这里找到。
其他改进
如果你能想到其他的改进或改编,请随意在下面的评论中提出,这可能会引发讨论或激发我的后续项目。
技术堆栈
Ffmpeg、Acapella extractor、Mp3cut.net、Python (Matplotlib、Seaborn、nltk、SoundEx、SciPy、PyDub、NumPy、Pandas)和 Power BI。
关于我:我叫布鲁诺,是欧盟委员会的数据科学顾问。你可以通过我的网址与我联系:https://www . zhongtron . me
我的朋友 Frederik Caenepeel 博士为这个项目做出了贡献,也可以在LinkedIn上找到。
使用深度学习检测 CERN CMS 实验中的μ子动量
理解大数据
图 CMS 束管的移除(图片由 Maximilien Brice/Julien Ordan/CERN 提供——来源: CERN
在欧洲核子研究中心 CMS 实验中探测μ介子是一项重要的任务。欧洲核子研究中心的 CMS 物理项目深入研究了许多物理实验,通常预期会产生μ子。例如,研究著名的希格斯玻色子粒子的一种方法是通过一个衰变通道,在那里希格斯玻色子衰变为四个μ子。
由于μ子可以穿透几米厚的铁而没有明显的能量损失,它们很难被 CMS 系统的任何一层阻止。因此,μ子探测器是最外面的,远离相互作用点。当前μ子横向动量探测器、桶μ子轨迹探测器使用查找表来估计μ子的横向动量。后者是使用伪快度η测量的**,伪快度η是与带电粒子从这些碰撞中出现的角度相关的空间量,方位角φ是碰撞路径与 z 轴形成的角度。(来源: CMS 一级触发带有机器学习的μ子动量分配 —托马索·迪奥塔列维)**
图 2:采用的坐标系
在这个水平上的μ介子的任何检测被称为触发。
问题描述
需要更加复杂的技术来提高动量检测的精度以降低触发率。由于瞬发μ子光谱遵循指数分布,精度上的任何微小改进都可以显著减少触发的数量,特别是通过减少被误归类为高动量μ子的低动量μ子的数量。
这就是机器学习发挥作用的地方。通过应用更智能的算法,如神经网络、,我们可以提高触发系统的精度,以准确检测μ子及其相应的横向动量。(来源: CMS 一级触发带有机器学习的μ子动量分配——托马索·迪奥塔列维)
在下面的文章中,我们将应用几种深度学习方法来准确预测μ介子动量。我们将在 CMS 实验中使用来自阴极条室(CSC)的蒙特卡罗模拟数据。该数据集包含超过 300 万个利用皮媞亚产生的μ子事件。
探索数据集
我们检索的数据组织如下:
- 有 87 个特征 : 84 个与探测器相关;3 个作为路径变量
- CSC 内部有 12 个探测器面,每个探测器面有 7 个特征 (12*7=84)
这些功能组织如下:
- 0–11:φ坐标
- 12–23:角坐标
- 24–35:弯曲角度
- 36–47:时间信息
- 48–59:环号
- 60–71:前/后击
- 72–83:面罩
- 84–86:X _ road
- 87:φ角度
- 88 : Eta 角度
- 89 : q/pt(横向μ子动量)——目标标签
在μ介子室内,有多个探测器站,如下图所示。这些探测器平面被组织在特定的室中。
图 3:CMS 象限的示意图(来源: CERN 文件服务器)
然而,我们只关心 CSC 室中的μ介子击中,因此只与 CSC 室相关的特征。
让我们首先删除那些不需要的特性:
现在我们已经删除了这些要素,接下来我们可以将所有要素放入一个紧凑的 Pandas 数据框中,以便于以后进行数据分析。
探索性数据分析
让我们用熊猫的描述方法来看一下数据统计:
表 1:具有缺失值的要素的统计数据
快速查看会发现一些特征,如φangle 1、 Theta angle1 和 Bend angle1 有一些缺失值。让我们找出每个要素的空值的确切百分比:
图 4:缺失值分布
我们注意到前/后 1 、φ角度 1 、θ角度 1 、弯曲角度 1 、时间 1 和环 1 特征有超过 70%的缺失值!我们需要稍后删除这些特性,对于缺失值少于 25%的其他特性,我们将用每列的平均值填充缺失值。
接下来,我们将可视化所有特征的数据分布。
图 5:选定的特性直方图
我们注意到如上图所示,如果我们想要提高模型的学习速度,一些特征如 Theta angle1 、 Theta angle2 、 Theta angle3 和 X Road1 需要转换成正态分布(使用标准化)。
预处理用于训练的数据
将问题框定为分类任务
不要试图应用回归来预测μ子动量值( q/pt ),让我们首先尝试将动量分成 4 类:0–10 GeV、10–30 GeV、30–100 GeV 和> 100 GeV ,并因此将问题构建为分类任务。
为了对动量进行分组,我们将使用目标特征的倒数的绝对值(pt/q) 。让我们来看看这个新生成的要素的数据分布
图 6:pt/q 的数据分布
如图所示,很明显存在不同大小的不同组。让我们使用 Pandas 的 cut 方法对数据进行聚类,并检查新生成的组分布。
图 7:目标类的数据分布
现在我们已经成功地将标签分组,我们可以观察到类不平衡,因此每当我们开始训练我们的神经网络以避免任何偏差时,我们都需要平衡它们。
将数据集分为训练集和测试集
接下来,让我们将数据分为训练和测试数据,我们将使用 90%-10%的分割。重要的是使测试集代表原始数据集中的目标类分布。因此,我们将使用 Scikit-Learn 中的 StratifiedShuffleSplit 方法来使训练数据和测试数据都代表类的原始分布,而不是随机分割我们的原始数据集。
让我们检查新生成的集合中的类分布:
表 2:比较原始、训练和测试集之间的类分布
如上表所示,训练集和测试集都代表原始数据集。我们现在可以安全地进入预处理的最后一步:准备管道。
准备预处理管道
该管道将执行以下任务:
- 删除缺失值超过 70%的列
- 使用 Scikit-Learn 简单估算器用相应的方法估算缺失值的其他列
- 用 Scikit-Learn 标准定标器将数据标准化
- 将目标特征编码成四个一个热编码特征
以下是管道完整代码:
构建神经网络
我们将使用 Tensorflow 的 Keras 库来构建我们的神经网络。神经网络将有 5 个隐藏层,每层的神经元数量为 512、256、128、64 和 32 。我们还在网络中添加了脱落层以减少过度拟合。输出层将有 4 个神经元(与类的数量相同),我们将对每个输出神经元应用 softmax 激活函数,以获得每个类的概率。
由于这是一个分类任务,我们选择的损失函数是**分类交叉熵,**和 Adam 将被用作优化器:
让我们为模型设置一些回调,包括一个检查点回调和提前停止回调,它们都将监控模型的验证准确性。我们将使用 25%的验证分割、500的批量,并将训练 200 个周期。现在我们终于可以开始训练了!
现在我们已经完成了模型的训练,让我们来看看它在训练时期的性能演变。
图 8:分类器度量在训练时期的演变
看起来我们在验证集上达到了 84%的准确率。令人印象深刻!但如果说我从机器学习中学到了什么的话,那就是从来不依靠准确性,只依靠和来判断模型性能。我们需要更深入地了解这个案例。
测试模型
让我们使用 Scikit-Learn 的分类报告来检查模型在训练集和测试集上的性能。它包括一系列重要的分类指标,包括精确度、召回率和 f1 分数:
表 3:列车数据评估报告
表 4:测试数据评估报告
令人印象深刻!似乎增加类别权重肯定会减少偏差,我们在测试数据上达到了 0.85 的加权 f1 分数!
回归实验
让我们尝试直接预测每个μ子动量的 q/pT 值,而不是将目标标签分成四组,因此将问题框架化为回归任务。我们只改变了模型的最后一层,用一个线性激活函数的输出神经元代替了 softmax 的 4 个神经元。
由于这是一个回归任务,我们将选择均方误差作为我们的损失函数,类似于分类任务,我们将使用 Adam 作为优化器。
让我们来看看回归模型在训练时期的性能演变:
图 8:模型训练的演变和训练时期的验证损失
让我们在训练集和测试集上检查模型的性能。我们将找到均方根误差,以便更好地了解这些值:
训练数据的均方根误差为 0.046,测试数据的均方根误差为 0.047 。一点都不差!与目标值相比,这些值似乎是相对可接受的,但肯定还有改进的空间。
未来方向
- 我们发现分类器模型在检测少数类方面不太好。因此,我们需要寻找更多的技术来使模型更少偏差(例如上采样少数类或下采样多数类)。
- 我们可以通过网格搜索调整超参数来进一步提高我们的回归模型的性能。
最后的想法
在这个项目中,我们尝试了几种深度学习方法来准确预测μ介子动量。首先,在预处理用于训练的数据之前,我们研究了数据属性。然后,我们训练一个分类器来预测μ子动量类别,并使用多重分类度量来评估分类器对新数据的性能。接下来,我们训练了一个回归模型来预测μ子动量值而不是它们的类别。这两种方法都相当成功,我们计划采用更先进的技术来减少模型偏差并提高性能。
原载于 2020 年 11 月 14 日【https://anisdismail.com】。
探测颤动中的物体
实践教程,全面的指南
使用 tflite 和 SSD-MobileNet
照片由韦斯顿·麦金农在 Unsplash 上拍摄|只是一些:D 的物品
介绍
在本指南中,我们将使用 tflite 包和预训练的 SSD-MobileNet 模型在 Flutter 中开发一个应用程序,能够检测图像和实时摄像机流中的对象。这个应用程序能够离线检测对象。我们还将能够从应用程序中拍照,并将其输入到模型中进行检测。
使用 Flutter 和 TensorFlow Lite 的对象检测应用程序。GitHub 是超过 5000 万开发者共同工作的家园…
github.com](https://github.com/rupakkarki27/object_detection)
请注意,由于我繁忙的日程安排,我不再维护这个项目。最近版本的 Flutter 和 dependencies 中引入的突破性变化可能会破坏应用程序。但你可以自由选择回购,按照自己的方式改变事情。谢谢!
设置项目
如果您还没有安装,安装程序会在您机器上跳动。Flutter 网站上的这个指南是一个很好的起点。设置 Flutter 后,在终端中输入以下命令创建一个新项目。
$ flutter create object_detection
$ cd object_detection
现在,您可以在您喜欢的编辑器中打开您的项目。
安装软件包
在您的 pubspec.yaml 文件中,在 dependencies 部分下添加以下内容以安装所需的包。
image_picker: ^0.6.7
tflite: ^1.1.1
camera: ^0.5.8+7
我们使用 image_picker 从图库中选取图像,使用 tflite 运行我们的模型,使用 camera 包控制相机。你可以在 pub.dev 上读到更多关于他们的信息。
在您的应用程序级别 build.gradl e 文件(/android/app)中,在 android 块下添加以下行,以确保 Flutter 不会压缩您的模型或 tflite 包。
aaptOptions {
noCompress 'tflite'
noCompress 'lite'
}
模型
您可以从上面提到的 GitHub repo 或任何地方下载 SSD-MobileNet 模型及其标签,并将它们放在您的项目中。然后,在您的 pubspec.yaml 文件中添加您的资产。
assets:
- assets/models/ssd_mobilenet.tflite
- assets/models/labels.txt
初始化摄像机
该应用程序的主要功能是以这样一种方式创建的,即所有的摄像机在应用程序启动后立即初始化。然后,摄像机描述被传递给所有需要它的类。
初始化摄像机的主要功能
图像中的目标检测
为了检测图像中的对象,我们首先需要使用 tflite 包中的 Tflite.loadModel 方法加载模型。然后,我们需要从我们的图库中获取图像,或者通过启动相机从应用程序中拍摄一张图像。相机包提供了获取图像的方法,这两种方法都可以使用。
加载图像后,我们使用TF lite . detectobjectonimage方法将它输入到我们的模型中。该方法返回检测到的类别、置信度和兴趣点,这将帮助我们在对象周围绘制边界框。
各种操作的功能
绘制边界框
围绕检测到的对象绘制边界框的基本思想是使用来自模型的兴趣点和图像尺寸。
使用堆栈小部件,我们可以将边界框放在图像的顶部。在定位的小部件中,我们放置一个四周有边框的容器。我们还可以通过简单地添加一个文本小部件并将置信度转换为百分比,以百分比的形式显示检测到的类及其准确性。
边界框的代码
静态图像检测页面有两个浮动操作按钮。使用其中一个,我们可以直接从图库中挑选图像,并在上面运行我们的模型。使用另一个,一个相机被打开,我们可以拍照,并把它提供给我们的模型。
模型检测图像中的对象(图片由作者提供)
实时目标检测
实时检测对象有点类似于检测图像中的对象。视频流中的每一帧都被视为一幅图像,模型在其上运行。该模型每帧输出结果,边界框在图像流上被一遍又一遍地重画。
相机插件中的相机控制器对象有一个名为 startImageStream 的方法,可用于向我们的模型提供帧。在这个方法中,我们可以调用TF lite . detectobjectonframe方法,该方法获取相机流并在我们的模型中运行它。该方法的其余部分是相同的,即模型返回 detectedClass、confidence 和 poi,我们使用它们在相机流的顶部绘制边界框。
实时检测
实时检测(GIF 由作者提供)
结论
我们开发了一个能够使用 Flutter、 tflite 包和一个预训练模型来检测对象的应用程序。该应用程序并不完美,可能无法在所有图像上工作。我们可以通过训练我们自己的模型来改善这一点,该模型可以以更高的准确性检测更多的类,或者使用其他一些强大的模型。
尽管有这个障碍,该应用程序在图像和视频光照良好的情况下表现非常好。对于那些希望将机器学习和 Flutter 知识结合起来的人来说,这是一个非常好的项目。我们还可以使用谷歌的可教机器来训练模型对特定类型的图像进行分类或检测。
tflite 插件目前只支持 SSD-MobileNet 和 YOLO 进行物体检测。
你可以在这里 查看项目回购 。如果有任何问题,请随时打开问题或创建一个公关。欢迎并鼓励任何反馈或建议。
你也可以在这里 看看我的作品集 。
在 Java 中从胸部 x 射线图像中检测肺炎
基于 Keras 和 Deep Java 库的图像分类
免责声明:这篇博文仅用于教育目的。该应用程序是使用实验代码开发的。该结果不应用于肺炎的任何医学诊断。此内容尚未经过任何科学家或医学专业人士的审核或批准。
介绍
在这篇博客文章中,我们展示了深度学习(DL)如何用于从胸部 x 光图像中检测肺炎。这项工作的灵感来自 Kaggle 上的胸部 x 光图像挑战和一篇相关论文。在这篇文章中,我们通过关注企业部署来说明人工智能如何帮助临床决策。这项工作利用了使用 Keras 和 TensorFlow 与 Kaggle 内核训练的模型。在这篇博文中,我们将重点关注使用 Deep Java Library (DJL),一个用 Java 构建和部署 DL 的开源库,用这个模型生成预测。
软件设置
我们选择了 Keras 和 DJL ,两个用户友好的 DL 工具来实现我们的图像分类器。Keras 是一个易于使用的高级深度学习 API,支持快速原型制作。与此同时,DJL 为 Keras 用户提供了简单的 API 来在 Java 中部署 DL 模型。现在,让我们深入教程。
使用 Keras 训练并保存您的模型
第一步是训练图像分类模型。你可以按照这个内核中引用的指令来获得一步一步的指导。该模型试图通过目视检查胸部 x 光图像中的特征来识别肺炎。作为一个参考点,下面的图像比较了三个具有正常肺(左)、细菌性肺炎(中)和病毒性肺炎(右)的候选人之间的差异。[1]
图 1 据 论文图 S6,正常胸片(左)示双肺清晰,细菌性肺炎(中)示局灶性肺叶实变,病毒性肺炎(右)示双肺更弥漫性“间质”样改变。
训练过程包括 3 个步骤:准备数据、构建模型和训练模型。您可以使用此链接下载用于训练该模型的数据集。该模型由深度方向可分离的卷积层组成,具有 ImageNet 上的部分预训练权重。深度方向可分离的卷积层具有更少的参数,并且比可比较的 DL 模型更有效。我们还使用了迁移学习,这是一种流行的 DL 技术,它将针对一个问题训练的模型应用于另一个相关的问题。迁移学习利用在类似问题上已经学到的特征,而不是从零开始开发模型,并且快速产生更健壮的模型。对于我们模型中的前 2 层,我们使用了一个 VGG 网络的权重,该网络是在 ImageNet 上预先训练的,这是一个大得多的数据集。
你可以直接下载内核笔记本,在本地运行来生成模型。注意,我们需要将模型保存为 TensorFlow 保存的模型格式。你可以在笔记本的最后加上下面一行。有关在 DJL 使用 Keras 模型的更多信息,请参见如何在 DJL 导入 Keras 模型。
model.save("best_model")
如果你想用预先训练好的模型直接运行预测,从下载这个模型开始。
使用深度 Java 库加载和运行预测
一旦有了训练好的模型,就可以使用 DJL 生成预测。完整代码见肺炎检测。您可以使用以下命令从命令行运行预测。使用-Dai.djl.repository.zoo.location
指定模型的位置。
以下是输出示例:
下面几节将带您详细了解代码。
导入 DJL 库和 TensorFlow 引擎
要在 Keras 模型上运行预测,您需要 DJL 高级 API 库和底层 TensorFlow 引擎。它们可以使用 Gradle 或 Maven 导入。更多详情,请参见肺炎检测自述文件。以下示例使用 Gradle 来设置依赖关系:
负荷模型和运行预测
接下来,我们需要加载我们训练好的模型。DJL 提供了简单易用的 API 来加载模型。你可以使用我们的模型动物园来加载模型,或者从你的本地驱动器使用你自己的模型。以下示例使用本地模型动物园来加载模型并运行预测。这只用几行代码就可以完成。
在这段代码中,我们首先使用一个 Criteria builder 来告诉 model zoo 我们想要加载什么样的模型。我们在这里指定希望加载一个模型,将一个[BufferedImage](https://javadoc.io/doc/ai.djl/api/latest/ai/djl/modality/cv/util/BufferedImageUtils.html)
作为输入,并预测一个[Classifications](https://javadoc.io/doc/ai.djl/api/latest/ai/djl/modality/Classifications.html)
作为结果。然后我们可以使用ModelZoo.loadModel
在模型库中找到匹配的模型。默认情况下,DJL 将在我们的内置库中寻找模型。我们需要告诉 DJL 查看一个自定义路径,该路径包含我们在培训部分获得的 TensorFlow SavedModel 格式。我们可以通过指定`【T3]来做到这一点。之后,我们创建一个新的预测器来运行预测并打印出分类结果。这非常简单明了。
定义你的翻译
当我们加载模型时,我们还想定义如何预处理模型的输入数据和后处理模型的输出数据。DJL 为这个函数使用了[Translator](https://javadoc.io/doc/ai.djl/api/latest/ai/djl/modality/cv/translator/package-summary.html)
类。下面是实现过程:
转换器将输入数据格式从[BufferedImage](https://javadoc.io/doc/ai.djl/api/latest/ai/djl/modality/cv/util/BufferedImageUtils.html)
转换为[NDArray](https://javadoc.io/doc/ai.djl/api/latest/ai/djl/ndarray/NDArray.html)
,以符合模型的要求。它还将图像的大小调整为 224x224,并在将图像输入模型之前,通过除以 255 使图像正常化。运行推理时,您需要遵循在训练期间使用的相同预处理过程。在这种情况下,我们需要匹配 Keras 训练代码。运行预测后,模型将每个类别的概率输出为一个数组。然后,我们将这些预测转换回我们想要的类别,即“肺炎”或“正常”。
下一步是什么?
就是这样!我们已经完成了对 x 光图像的预测。现在,您可以尝试构建更复杂的模型,并尝试使用更大的数据集进行学习。关注我们的 GitHub 、演示库和 twitter 获取更多关于 DJL 的文档和示例!
关于 DJL
DJL 是一个用 Java 编写的深度学习框架,支持训练和推理。用户可以轻松地使用 DJL 部署他们喜欢的模型,而无需为各种引擎进行额外的转换。它包含 ModelZoo 概念,允许用户在 1 行中加载深度学习模型。DJL 模型动物园现在支持 70 多个预先训练好的模型,如 GluonCV、HuggingFace、TorchHub 和 Keras。
NDArray 的加入使其成为 Java 中运行深度学习应用的最佳工具包。它可以自动识别您运行的平台,并判断是否利用 GPU 来运行您的应用程序。
从最新发布的版本来看,DJL 0.5.0 正式支持 MXNet 1.7.0、PyTorch 1.5.0、TensorFlow 2.1.0。它还有一个 PyTorch Android 的实验引擎。
参考资料:
[1] 通过基于图像的深度学习识别医疗诊断和可治疗疾病
【2】企业最常用的 10 种编程语言:2019 版
【3】胸部 x 光图像(肺炎)
【4】胸部 x 光图像的内核
利用深度学习从胸片中检测肺炎
建立各种模型,并使用预先训练的模型从胸部 x 光诊断肺炎
疾控中心在 Unsplash 拍摄的照片
来自《走向数据科学》编辑的提示: 虽然我们允许独立作者根据我们的 规则和指导方针 发表文章,但我们不认可每个作者的贡献。你不应该在没有寻求专业建议的情况下依赖一个作者的作品。详见我们的 读者术语 。
2017 年有 256 万人死于肺炎。这些人中大约三分之一是不到 5 岁的儿童。世卫组织估计,这些过早死亡中有 45,000 例是由于家庭空气污染。随着诊断效率的提高,许多死亡可以减少。
这个项目的目标是创建各种机器学习和深度学习模型,以便在优化后,可以帮助放射科医生从胸部 x 光片中检测肺炎。
环境和工具
在整个项目中,我们将使用 python,因此建议您使用一些编辑器,如 Google Colaboratory,这些编辑器与 python 兼容,但也允许使用某些 python 包。
我们将使用 python 包:
- Numpy
- 熊猫
- Tensorflow(版本 1.x)
- Sci-Kit Learn 和 Keras
- Seaborn 和 Matplotlib
我们将使用其他包来下载与构建模型无关的文件和辅助函数。要获得完整的列表,请查看下面附加的代码。
项目和代码
既然我们已经有了所有的介绍,让我们开始吧。
我们将从导入一些关键包开始,我们将在整个项目中使用这些包。我们还将为项目下载数据(在这种情况下,胸部 x 光图像)。
你可以在 Github 上找到完整的代码。
在开始构建各种模型之前,我们必须分析并熟悉我们的数据。让我们下载一个名为“元数据”的文件,它为我们提供了关于数据的关键信息。之后,我们将使用 pandas 库创建一个数据框(本质上是一个表),它将提供关于我们数据集中前五幅图像的信息。
作者图片
表格中的每一行代表一幅胸部 x 光图像。您可以看到三列:类别、拆分和索引。级别为 0 或 1,0 表示肺部健康,1 表示肺部有肺炎。索引是图像的标签,它告诉我们正在查看数据集中的哪个图像。
关于分裂,当我们教计算机如何做某事(在这种情况下诊断肺炎)时,我们必须通过给图像加标签来训练它。但是,我们也要通过给计算机不同的以前没见过的图像来测试计算机,让计算机来决定肺部有没有肺炎。因此,拆分列描述了图像是用于训练计算机还是测试计算机。下面是我做的一个图表,用来帮助区分这两者。
作者图片
现在,制作所给信息的图表,进一步分类每个类别中有多少张图片,并进行分割。我们将使用 pandas 方法“count”来显示该表,并且我们将使用 seaborn“count plot”来显示一个对数据进行分类的图表。
作者图片
作者图片
如图表所示,1200 个肺是健康的,1200 个肺有肺炎。在这 1200 个中,一千个将用于训练模型,另一千个将用于测试模型。
现在我们已经完全了解了我们的数据属于哪一类,我们可以继续绘制一些图像,以查看胸部 x 射线将会是什么样子。
运行此功能,允许您绘制图像:
在这里,您可以通过运行下面的代码来调用该函数。它下载训练和测试数据(从我们之前定义的函数中),并根据索引(与图像相关的数字)绘制图像。注意第 4 行的 1)。“数据”是图像,而“标签”部分是数字 0 或 1,表示患者是否患有肺炎。
我特别选择了一张健康的照片,和一张肺部有肺炎的照片。您可以随意使用索引来查看其他图像。
左图是健康的肺,右图是肺炎。作者提供的图片
简单的机器学习模型
现在,我们已经完成了对数据的检查和分析,我们可以继续构建一些机器学习模型。我们将从简单的开始,使用 K-最近邻和逻辑回归分类器。
k-最近邻
K-最近邻的关键概念是,当我们看到一个未知的例子时,我们也会看到这个未知的最接近的例子,并预测它是同一个例子。
作者图片
上图显示了 K-最近邻分类器。例如,如果 k=1,与所讨论的形状最接近的(单个)形状是圆形。因此,如果 k=1,形状是圆形。然而,如果 k=3,与所讨论的形状最接近的 3 个形状是 2 个矩形和 1 个圆形。所以,如果 k=3,形状是长方形。
逻辑回归
逻辑回归用于预测概率,这些概率随后会变成一个类别(0–1)。在线性回归中,预测的 y 值可能会超过 0–1 范围(使用连续直线)。但是,在逻辑回归中,预测的 y 值不能超过 0–1 的范围,因为它呈“s”形。举例来说,请看下图。
图片由 Michaelg2015 在公共领域发布
x 轴显示学生学习的小时数,y 轴显示他们是否通过了考试(0 或 1)。然而,逻辑曲线的 y 轴显示了他们是否通过考试的概率。如你所见,曲线预测学习少的人会不及格,而不是及格,反之亦然。
构建机器学习模型
我们将使用 sci-kit learn 库来构建这些模型,特别是 KNeighborsClassifier 和 LogisticRegression 方法。
建立机器学习模型的步骤是加载模型,拟合(或训练)模型,用模型预测病人是否患有肺炎,最后对模型进行评估。
正如您所看到的,在第 6 行和第 7 行,我们加载或初始化了模型。然后,在第 10 行和第 11 行,我们使用训练数据训练模型。对于预测,模型根据 test_data 预测 test _ labels 是什么。这就是为什么,为了检查准确性分数,我们基于 test_data 检查我们的预测如何。
现在,我们可以运行模型并检查准确性分数。请注意,您可以通过更改邻居的数量来提高 KNN 分类器的性能。
准确度分数
很明显,这些模型的准确度分数很低。因此,这些不是解决这个问题的最佳模型。所以,我们必须采取不同的方法。
卷积神经网络
卷积神经网络是一种特定类型的神经网络,用于查找图像之间的模式。我将简要描述 3 个关键部分:
- 盘旋
- 联营
- 完全连接的层
盘旋
卷积核是一个权重矩阵,类似于全连接层的权重矩阵。通过将权重与图像输入中的相应像素值逐元素相乘,将卷积核应用于输入。这将有助于锐化图像。
迈克尔·普罗特克在公共领域发布的图片
联营
卷积层输出仍然太大,神经网络无法做出任何预测。我们可以通过汇集来减少它的规模。它将卷积层中的某些像素组合起来,并将其合并成一个像素。最大池化是最常见的池化示例之一,它将输出分成多个分块,并取每个分块的最大值。
图片由 Aphex34 在公共领域发布
完全连接的层
完全连接层将单个神经元中的每个神经元连接到下一层中的所有其他神经元。最后一层使用输出概率的激活函数,如 softmax 或 sigmoid,计算机将使用这些函数对图像进行分类。
图片由 Kjell Magne Fauske 在公共领域发布
构建我们的卷积神经网络
我们将使用 Keras 库来构建我们的模型。在你建立你的模型之前,运行这两个函数,这将允许你绘制精确度和损失。
现在,我们已经运行了这些函数,让我们来构建模型。您必须了解一些关键组件,它们是:
- add(Conv2D()) :执行卷积的层。它需要三个参数。第一个是它执行卷积的次数,第二个是卷积的维数,第三个是激活函数。对于第一层,请确保也指定了输入形状。
- 添加(MaxPooling2D()): 执行最大池的层。它接受 1 个参数,即组合像素的尺寸。
- add(Flatten()): 将图像展平成一维数组。
- add(Dense()): 添加一个全连接层。它接受两个参数,该层中神经元的数量,以及该层的激活函数。
- add(Dropout(): 关闭一定数量的神经元,以减少过度拟合。接受一个参数,通常是一个介于 0 和 1 之间的数字,当转换成百分比时,就是前几层中被切断的神经元的百分比。
- 我们对每一层(除了输出层)的激活函数将是 ReLU 。对于我们的输出层,激活函数将是 sigmoid ,它输出我们的患者是否患有肺炎的概率。
- 我们的损失将是 binary_crossentropy ,我们将使用优化器 RMSprop ,定制为 1e-4 的学习速率和 1e-6 的衰减。
太好了!现在我们已经构建了模型,让我们运行它,看看它做得有多好。
作者提供的图片
从上面的图中可以看出,我们的模型做得相当好。然而,它的表现还不够好,不能用于临床。您可以从这里继续修补模型,以提高准确性和减少损失。但是,确保避免过拟合(当计算机记忆训练数据时,因此它在测试数据上表现很差。
如何阅读图表
x 轴显示了历元的数量。只要 x 轴上有小数,就可以忽略它,因为只允许完整的历元(整数)。在 y 轴上,您有您正在测量的值。可能是损耗,精度等。黄线表示训练数据,而蓝线表示验证数据。绿线代表该指标的最佳时期。
迁移学习
对于我们的迁移学习,我们将使用 VGG16。VGG16 是在“ImageNet”分类问题中使用的“专家”模型。在 ImageNet 中,参赛者被要求建立能够区分 1400 万个图像类别的模型,其中有超过 20,000 个类别可用。
VGG16 被允许研究这 1400 万张图像 74 次。然后,它能够比人类更好地猜测图像的真实标签。
我们将带着 VGG16,让它在我们的 x 射线上训练。希望他们在 ImageNet 问题上的经验将有助于区分肺炎和我们的 x 光片。
第一行将下载 VGG16 的卷积算法。然后我们将不得不声明它是可训练的,通过使用一个“for”循环,确保我们可以训练每一层。之后,我们必须添加和自定义完全连接的层,因为 VGG16 包含固定的卷积层。
现在,运行它,让我们看看它的表现如何!
如您所见,我们的模型的性能随着 VGG16 的使用而显著提高。您还可以看到,模型在 1-2 个时期后开始过度拟合。这是因为 VGG16 是预先训练好的,这使得它更有效和准确,但同时,它也更容易过度拟合。
结论
我们开始这个项目是通过分析我们学到的数据,并了解有多少图像患有肺炎或健康。我们还将数据集分为训练数据和测试数据。之后,我们构建了简单的机器学习模型,这些模型能够根据我们对其进行的训练做出明智的决策。最后,我们构建了卷积神经网络来提高模型的精度和效率。之后,我们使用一个预先训练好的模型作为我们的迁移学习来进一步优化我们的模型。现在,我把它留给你。你如何继续改进这个模型,使它能够用于医疗实践?也许你甚至可以在一些现场数据上运行它,并应用数据扩充。
参考文献
[1]匿名,分类(未标明),可教授
[2]无名氏,肺炎 (2019),世界卫生组织
[2] B. Dadonaite 和 M. Roser,肺炎 (2019),数据中的我们的世界
[3] C .阿奇,利用卷积神经网络进行胸部 X 线肺炎检测 (2020),Medium.com
[4] R. Prabhu,对卷积神经网络(CNN)的理解—深度学习 (2018),Medium.com
感谢 Inspirit AI 教会了我所有的技术细节并提供了数据集。
用 CNN 建立图像分类模型
用卷积神经网络检测肺炎
正常和肺炎 X 射线的特征图像
在这篇博客中,我将概述如何使用卷积神经网络建立一个简单的图像分类模型,以从胸部 X 射线图像中检测肺炎的存在。
肺炎是一种常见的感染,它使肺部的气囊发炎,导致呼吸困难和发烧等症状。尽管肺炎不难治疗,但及时诊断至关重要。如果没有适当的治疗,肺炎可能会致命,特别是在儿童和老年人中。胸部 x 光检查是诊断肺炎的一种负担得起的方法。开发一种能够从 X 射线图像中可靠地对肺炎进行分类的模型,可以减轻需求高的地区的医生的负担。
数据
Kermany 和他在 UCSD 的同事们利用深度学习,基于胸部 X 射线和光学相干断层扫描,主动识别疾病。我们使用他们研究中提供的胸部 x 光图像作为我们的数据集。
[## 标记的光学相干断层扫描(OCT)和胸部 X 射线图像的大型数据集
确保下载该数据集的最新版本,以保持准确性。该数据集包含数千个…
data.mendeley.com](https://data.mendeley.com/datasets/rscbjbr9sj/3)
数据结构
数据文件夹的结构如下。
DATA
│
├── train
│ ├── NORMAL
│ └── PNEUMONIA
│
├── test
│ ├── NORMAL
│ └── PNEUMONIA
│
└── validation
├── NORMAL
└── PNEUMONIA
在删除没有适当编码的图像文件后,我们的数据集中有 5,639 个文件,我们将这些图像中的 15%用作验证集,另外 15%用作测试集。我们的最终训练集包括 1,076 个正常病例和 2,873 个肺炎病例。
数据探索
如果您对在图像数据上运行探索性数据分析的步骤感兴趣,请参见我以前的帖子。
图像数据的可视化模式
towardsdatascience.com](/exploratory-data-analysis-ideas-for-image-classification-d3fc6bbfb2d2)
我们的探索性数据可视化显示,肺部炎症通常会阻碍心脏和胸腔的可见性,从而在肺部区域周围产生较大的可变性。
第一个模型
作为我们的基线模型,我们将构建一个简单的卷积神经网络,它在将图像调整为正方形矩阵并将所有像素值归一化为 0 到 1 的范围后接收图像。完整的步骤如下所示。
现在我将详细解释每个步骤。
1.缩放数据
keras.image.ImageDataGenerator()
拍摄图像并根据参数创建增强数据。在这里,我们只是要求它将所有像素值重新调整为 0 到 1,而不指定任何其他增强参数。与flow_from_directory
结合,生成器以指定的格式从目录中调用图像,然后创建重新缩放的数据。
2.构建模型架构
keras.models.Sequential()
启动顺序模式。该模型将顺序处理添加的层。
Conv2D
层是卷积层,它接收输入并通过指定数量的滤波器。内核大小指的是过滤器的尺寸。因此,在本例中,我们的 2562561 图像(1 表示通道数,RGB 图像有 3 个通道,而灰度图像有 1 个通道)中的每个连续 33 像素组将通过 32 个过滤器,生成 32 个大小为 256256*1 的特征图。
因为 256 不能被 3 整除,所以padding = ‘same'
用于在窗口周围添加相等的填充。
activation = 'relu'
意味着我们将调整后的线性单位指定为激活函数。简单来说,我们是在告诉层把我们所有的负值都转换成 0。
然后,我们将卷积层的这些输出馈入池层。MaxPooling2D
层通过仅保留卷积输出的每个 22 矩阵的最大值来提取卷积输出。现在,我们将有 32 个大小为 128128*1 的特征地图。
现在,我们需要将这些四维输出缩小到一个数字,它可以告诉我们是将图像分类为肺炎还是正常。我们首先将层展平成一维,然后让它们通过越来越小的致密层。sigmoid 函数作为激活函数应用于最后一层,因为我们现在希望模型输出一个输出是否为肺炎的概率。
3.配置
我们已经定义了模型的架构。下一步是决定这个模型的目标,以及我们希望它如何实现。使用model.compile
,我们告诉模型使用梯度下降来最小化二元交叉熵损失(对数损失,想想逻辑回归)。这里,我们使用 RMSprop 算法通过自适应降低学习速率来优化这个过程。在后来的模型中,我使用了 AMSGrad 算法,它对我们的问题表现得更好。
4.拟合数据
最后,我们完成了模型的构建。是时候拟合我们的训练数据了!默认情况下,每个时期将运行 32 个批次。我们设置EarlyStopping
是为了防止过度拟合。如果我们的验证损失连续 5 个时期没有减少,该模型将停止运行。我将restore_best_weights
设置为真,这样在这 5 个时期之后,它将恢复到最高的性能权重。它在我们之前创建的验证生成器上测试其性能。
5.估价
我们的第一个模型显示了 94%的准确性,预测了验证数据的类别,对数损失为 0.11。根据下图,我们可以看到培训损失有改进的空间,因此我们可以增加模型的复杂性。此外,验证损失似乎徘徊在 0.1 左右。我们可以尝试通过使用数据扩充来模仿添加更多数据,从而提高可推广性。
这里有一个完整的代码来绘制拟合模型的损失图和精度图。
模型 2
现在,我们将尝试实现数据扩充,并为我们的模型增加更多的复杂性。
数据扩充
这一次,我们向列车图像数据生成器添加了一些参数。因此,现在我们的生成器将通过对原始图像集应用指定范围内的不同旋转、亮度、剪切和缩放来为每批图像创建新图像。
模型复杂性
我们还通过增加三组卷积层和池层来增加模型的复杂性。建议随着图层的进展增加卷积过滤器的数量。这是因为当我们在这些层中移动时,我们试图提取更多的信息,因此需要更大的过滤器集。这个类比类似于我们的大脑处理视觉信息的方式。随着信号从我们的视网膜移动到视交叉,到丘脑,到初级视觉皮层,然后通过下颞叶皮层,神经元的感受野在每一步都变得更大,对复杂信息越来越敏感。
估价
我们的第二个模型显示了 97.3%的准确性,在验证集上的对数损失为 0.075。看来我们的调整确实改进了我们的模型!让我们在我们的测试集上测试它,以确保它们能很好地推广到看不见的数据。
最终性能
我们的模型以 97.8%的准确度预测了测试集中的 X 射线图像的类别。它成功地识别了 97.9%的肺炎病例。
结论
我们的模型表明,在给定数据集的情况下,使用卷积神经网络,它能够正确检测出接近 98%的肺炎病例。但尤其是对于生命受到威胁的医疗问题,即使只有 2%的漏诊病例也不应该简单地不予考虑。为了理解我们的模型的局限性,下一步重要的工作是对模型失败的地方进行详细的调查。
使用自然语言处理检测来自美国参议员的带有政治偏见的短语(教程)
气候危机、劳动人民和负担得起的健康?还是共产主义者,自由主义者,堕胎?
早在 3 月份,我观察了 2020 年疫情选举前的投票模式,并将其与相对两党对医改法案的投票进行了比较。现在,新冠肺炎疫情已经开展了几个月,其他事件正在成为焦点——即反对警察暴行和种族不公正的示威游行。此外,我们离共和党和民主党全国代表大会只有几个月的时间,选举随后就要到来。那么,政治家们在谈论什么呢?
为了掌握这一点,我决定用 VoteSmart.org 的(我从 T4 的一篇研究论文中得到这个想法)来看看政治演讲,并看看党派短语。帖子将按如下方式进行:
- 集合语料库
- 提取常用短语
- 衡量政治两极化短语
步骤 1:集合语料库
我从一个维护良好的数据集开始,这个数据集包含国会中的每个人,其中包含一个链接到他们的投票智能页面的 ID。为了便于阅读,我的目标是为每位立法者制作一个文件夹,其中包含他们所有发言的文本文件。我提到的研究论文使用了几种类型的演讲,但我包括了从 2020 年 1 月开始的所有类型的公开声明。
本教程将侧重于文本分析,但你可以在这里找到抓取语料库的代码。我用它从 VoteSmart 收集了超过 10,000 条独特的声明和演讲(我删除了推文和重复的声明),不过如果你对它进行微调,并不仅仅包括参议员,你还可以收集更多。以下是伯尼·桑德斯三月份接受 CNN 采访时的一段文字样本:
COOPER: Now to our interview with Senator Bernie Sanders. He is campaigning in the Super Tuesday state of Minnesota.Senator Sanders, thanks for being with us. You just heard Mayor Buttigieg endorsing Vice President Biden. Klobuchar is expected to do the same tonight, as is Beto O'Rourke. How does the consolidation of the moderate vote affect your plans moving forward, especially since Senator Warren shows no signs of getting out?SEN. BERNIE SANDERS (D-VT), PRESIDENTIAL CANDIDATE: Well, Anderson, I think, as you know, from day one we have been taking on the establishment, whether it is the corporate establishment, you know, Wall Street, the drug companies, the insurance companies, the fossil fuel industry, or the political establishment.And let me be very clear, it is no surprise they do not want me to become president because our administration will transform this country to create an economy and a government that works for all of the people, not just the 1 percent. It will not be the same old same old....
这是有组织的语料库的样子:
步骤 2:提取常用短语
下一步是通过将文本分割成标记来提取短语。我使用了 scikit-learn 的令牌矢量器,因为它有一些很棒的内置特性。下面是设置一切看起来有多简单:
from sklearn.feature_extraction.text import CountVectorizer
from nltk.corpus import stopwordsnltk_stop_words = stopwords.words('english')tf_vectorizer = CountVectorizer(max_df=0.8, min_df=50,
ngram_range = (1,2),
binary=True,
stop_words=nltk_stop_words)
停用词(即nltk_stop_words
)有助于去除无信息的单词,常见的例子有“of”、“to”和“and”我使用 NLTK 的列表是因为 scikit 的内置列表有一些已知的问题。然后,tf_vectorizer
(tf 代表“术语频率”)通过一些设置进行初始化:
max_df=0.8
意味着排除出现在 80%或更多文档中的短语(类似于停用词,它们不太可能提供信息,因为它们太常见了)min_df=50
意味着该词必须在语料库中出现至少 50 次才能被纳入分析(我使用 50 次,因为我提到的研究论文也是如此,尽管您可以尝试不同的临界值)ngram_range=(1,2)
意味着包括一个单词和两个单词的短语(你可以很容易地将它设置为(1,3)
来包括三元组/三个单词的短语binary=True
表示只计算一个单词在给定文档中出现的次数(即 0 或 1),而不是精确计算它出现的次数(即 0 或 1 或 2 或 3 或…)stop_words=nltk_stop_words
插入前一行中设置的 NLTK 停用词表,这样就不包括“of”和“to”这样的词
使用文件 I/O 将文本放入列表后,tf_vectorizer
可以将文本转换成只有一行的短语矩阵:
term_frequencies = tf_vectorizer.fit_transform(texts_list)
现在,term_frequences
是一个矩阵,包含来自矢量器的每一项的计数。我们可以把它变成一个数据框架,让事情更直观,看到最常见的短语:
phrases_df = pd.DataFrame(data=tf_vectorizer.get_feature_names(),columns=['phrase'])phrases_df['total_occurrences']=term_frequencies.sum(axis=0).Tphrases_df.sort_values(by='total_occurrences',ascending=False).head(20).to_csv('top_20_overall.csv',index=False)
生成的 csv 文件如下所示:
步骤 3:衡量政治两极化短语
首先,我们需要将民主党和共和党撰写的文章分开,然后得到它们的词频矩阵。熊猫数据框架让这变得相当容易:
dem_tfs = tf_vectorizer.transform(texts_df[texts_df.party=='Democrat'].text.tolist())rep_tfs = tf_vectorizer.transform(texts_df[texts_df.party=='Republican'].text.tolist())
现在到了有趣的部分:找出哪些短语带有政治色彩。以下是解释这种方法的文章部分(关键公式突出显示):
你可能会注意到公式中只有两个变量:民主党人撰写的文本的短语概率和共和党人撰写的文本的短语概率。因此,为了计算党派偏见分数,我们只需要计算这两个概率,我将其简称为p_dem
和p_rep
。一旦我们有了这些,每个短语的偏差分数就是:
bias = (p_rep - p_dem) / (p_rep + p_dem)
我使用了一个基本的概率度量:包含一个短语的文档数除以文档总数。有一些更复杂的方法来衡量概率,但根据我对论文的阅读,这可能是作者所做的。
快到了!现在,我们只需要将偏见分数放入之前的phrases_df
数据框架中,然后我们就可以轻松地查看一些常见的党派短语。当我第一次运行这个时,一些名字短语,如“参议员哈里斯”和“参议员帕蒂”是最具党派性的——一个抄本的人工制品。为了解决这个问题,我做了一个过滤器,以确保至少有三名参议员使用党派短语:
top_rep = phrases_df.sort_values(by='bias_score',ascending=False).head(100)top_rep['n_senators'] = top_rep.apply(lambda x: len(texts_df[texts_df.text.str.contains(x.phrase)].person.unique()),axis=1)top_rep = top_rep[top_rep.n_senators > 2]
现在,我们终于可以看到党派短语了!你会注意到他们与党派议程保持一致,例如,民主党人谈论气候危机和医疗保健,而共和党人谈论堕胎。
这里是最倾向于民主党的短语,以及我们计算的分数和概率。
和最倾向共和党的短语:
有了这些短语和它们的偏见分数,你可以衡量推特、演讲、文章等的政治偏见。通过计算党派短语的频率:如果一篇文章大量谈论未出生者、自由主义者和共产主义者,它可能倾向于共和党,而如果一篇文章谈论气候危机、劳动人民和可负担的健康,它可能倾向于民主党。
感谢阅读!所有代码都是可用的,语料库也将很快可用,在这个资源库:
分析美国参议员的党派短语。有助于 jackbandy/党派短语的发展,创造一个…
github.com](https://github.com/jackbandy/partisan-phrases)
检测流数据中的实时和无监督异常:一个起点
图 1:智能设备生成实时数据,这些数据可能会出现异常,如果我们不检测并正确管理它们,就会导致我们做出错误的数据驱动型决策。图片来自 pixabay.com。
传感器通过收集各种系统中的数据来实现物联网( 物联网 )。数据通常以实时方式产生,然后我们可能会发现自己被迫进行实时处理(流数据挖掘 [1】)。系统的行为并不总是恒定不变的,而是可能表现出一种不寻常的、明显不同于先前正常行为的行为( 异常【2】)。异常检测是有价值的,但在实践中,它可能会变成一项难以可靠执行的任务。
本文并不声称是方法和解决方案的详尽列表,但是对于那些第一次处理这个问题并且需要简单、可理解和可伸缩的解决方案的从业者来说,它确实是一个简单的切入点。异常可能存在于真实世界的应用中,例如欺诈预防、金融、能源需求或消耗、电子商务、网络安全、医疗诊断、社交媒体、预测性维护或故障检测等。本文分析了一些处理异常的算法。它们是 Welford 的算法,基于四分位数的解决方案,基于 z-score 度量的解决方案,以及基于机器学习的解决方案,称为*半空间树(HST)。*前 3 个解决方案基于统计指标/度量,而最后一个来自机器学习领域。
流媒体:游戏规则
与批处理学习相反,批处理学习【】中假设数据是静止的(历史数据是可用的),并且模型不连续地将新信息集成到已经构建的模型中, 流学习 对实时处理施加约束:
- 流中的实例(数据)在线到达(通常一次一个实例),并且最多可以被读取一次,这构成了处理数据流的最强约束,并且系统必须决定当前实例是应该被丢弃还是存档。
- 只有选定的过去实例可以通过将它们存储在内存中来访问,相对于数据流的大小,内存通常较小。当设计流学习算法时,我们必须考虑几个算法和统计因素。例如,我们必须面对这样一个事实,即由于我们不能存储所有的输入,我们不能撤销根据过去的数据做出的决策。
- 每个实例的处理时间必须小且恒定。
- 处理算法必须产生一个模型,该模型等同于由批次处理算法产生的模型。
这组约束是大多数现有的用于 bacth 处理的异常检测算法不适用于流应用的原因。
在大多数实际情况下,数据由一个连续的单变量数据集组成,其中关于异常的监督信息(有多少,在哪里)是不可用的。
威尔福德算法
Welford 的方法是一种可用的单程方法,用于计算运行方差或运行标准差。它可以通过查看 N 个和 N-1 个实例的平方差之和的差来导出。不需要为第二次传递存储数据[3]。为了将 Welford 的方法用于异常检测问题,我建议加入以下简单的修改。
我们创建一个上限(UL)和一个下限(LL)。当在线平均消耗*(橙色实线)* 克服这些限制中的任何一个(或 X 乘以在线标准偏差*,那么我们将该读数(实例)归类为异常。限值(黑色虚线)可计算如下:*
UP =在线平均消费+X *在线标准差
LL =在线平均消耗量-X *在线标准偏差
X 越高,我们假设的假阴性(FNs)就越多,而 X 越低,我们获得的假阳性(FPs)就越多。因此, X 的选择不是微不足道的,并且在该参数 X 与 FPs 和 FNs 之间存在权衡。然后,你需要定义 X=1,2,3,4,… 等等。取决于这个决定。如您所见,每次新实例到达时,在线平均消耗和限制都会在线更新。
代码:原方法的简单实现可以在这里找到。
注释:读数=0 应视为异常与否。您还注意到,根据读数和 X. 的不同,LL 可能低于 0,如果这对于您的图表是个问题,可以很容易地调整这一事实。请注意,如果您获得许多连续的异常,您可能需要将它们视为唯一的异常,或者甚至视为“异常”周期。最后,我想提一下使用大小为 *w、*的滑动窗口的可能性,并计算它上面的所有指标。
基于四分位数的解决方案
箱线图是一种基于一组数字汇总来表示数据集分布的流行方法:最小值、第一个四分位数(Q1 / 第 25 个百分位数)、中值、第三个四分位数(Q3/75 个百分位数)和最大值。这种表示可以告诉您异常值及其值。
图 5:箱线图的元素。图片修改自维基共享。
四分位距(IQR) 从 Q1 到 Q3,我们可以计算最大值和最小值如下:
最大值=Q3+1.5*IQR
最小值=Q3-1.5*IQR
(关于 boxplots 和 quartiles 的更多详细信息,我建议您查看以下文章:https://towardsdatascience . com/understanding-box plots-5e 2 df 7 bcbd 51)
然后,我们可以将所有高于最大值或低于最小值的点视为异常值。我们可以在线计算这些数字汇总。
**代码:**如你所见,这个解决方案很容易实现。对于懒惰的人来说,在已知的存储库或其他网站上有许多这种方法的可用实现。
注意:这里我们也可以使用前面提到的滑动窗口。
基于 z 分数度量的解决方案
标准分数或 z 分数( z )给出了一个数据实例离均值有多远的概念,即原始分数高于或低于总体均值多少个标准差。
实例 x *的 z 值可以计算为:*z =(x-μ)/σ
标准分数也可以通过在线方式计算。但这一次,我们使用了滑动窗口,然后被称为运行或移动 z 分数。给定此窗口大小 w ,移动 z 值将是每个实例偏离平均值的标准偏差数,其中平均值和标准偏差仅在之前的 w 实例中计算。
**代码:**如你所见,这个解决方案很容易实现。对于懒人来说,这个方法在众所周知的源代码库中有很多可用的实现。
半空间树
半空间树(HST) [4]是一个快速的单类异常检测器,用于进化数据流。它只需要正常的数据进行训练,并且在异常情况及时扩散时工作良好。如果在时间窗口内将异常打包在一起,效果并不好。这种技术是随机 HST 的集合,其中每个树结构都是在没有任何数据的情况下构建的,这使得该技术非常高效,因为它在适应进化的数据流时不需要模型重构。
这种技术是增量训练的,并且使用滑动窗口 w. 其他相关参数是集合中的树的数量( nt ),以及用于声明异常的阈值( th )。任何高于此阈值的实例预测概率都将被声明为异常:分数越低,当前实例越有可能是异常的。要了解更多关于所有参数的信息,请查看下面的代码部分,或这篇论文。
**代码:**这个解决方案可以在 Creme 或者 scikit-multiflow 中找到,这两个框架都是用 Python 实现的。
其他方法
它也值得特别注意一些其他已知的方法,其中包括:
- 局部异常因素(LOF,见此处更多细节),
- 单变量参数方法,如 Grubb 检验(平均值可能是离群值的 mak)或 Tietjen y Moore 检验(可能会遭受淹没),
- 不要忘记检查[5],在那里已经进行了许多检测器之间的广泛比较。
结论
- 正如您已经意识到的,所有这些技术都需要调整一个或多个参数,这些参数会影响它们在 FPs 和 FNs 方面的性能(参见 F1-score 性能指标)。
- 由于这是一个无人监管的场景,因此为了评估该技术的性能,以及正确地找到 FPs 和 FNs 之间的平衡,具有该领域的广泛知识是非常重要的。在任何情况下,他们的评价都是主观的,这就是领域知识至关重要的原因。
- 每种技术根据不同的标准发现异常,因此它们不一定与其分类相匹配(异常是/否)。但是我们可以找到相似之处,例如在基于度量的解决方案和 T2 的解决方案之间。
- 最后,您应该考虑将这些技术组合在一起的可能性,因为它们可以互补并检测不同类型的异常。
参考
[1] 比费特,a .,霍尔姆斯,g .,柯克比,r .,&普法林格,B. (2010)。Moa:海量在线分析。机器学习研究杂志,11(5 月),1601–1604。
[2]钱德拉,v .,米塔尔,v .,T15 库马尔,V. (2008 年 12 月)。序列数据异常检测技术的比较评估。2008 年第八届 IEEE 数据挖掘国际会议(第 743-748 页)。IEEE。
[3] Knuth,D. E. (2014)。计算机编程艺术,第 2 卷:半数值算法。艾迪森-韦斯利专业版。
[4] S.C.Tan,K.M.Ting,和 T.F.Liu,“流数据的快速异常检测”,载于《国际人工智能联合会议论文集》, 2011 年,第 22 卷,第 1 期,第 1511-1516 页。
[5] 艾哈迈德,s .,拉文,a .,波弟,&阿迦,Z. (2017)。流数据的无监督实时异常检测。神经计算,262,134–147。
用变形金刚探测国家支持的推特巨魔
一个在定制数据集上微调 Distilbert 模型的实际用例,并针对更常用的模型(如逻辑回归和 XGBoost)测试其性能
web 应用程序插图作者:蔡金汉
随着 2020 年美国大选的临近,对国家行为者通过社交媒体和其他在线手段干预选举的担忧再次成为人们关注的焦点。
Twitter 是俄罗斯用来干涉 2016 年美国大选的一个主要平台,很少有人怀疑俄罗斯、中国和其他国家会再次转向这个平台,发起新的造谣运动。
这篇文章将概述如何通过使用自定义数据集微调 transformer 模型( Distilbert )来构建 state troll tweets 检测器。这建立在我的早期项目的基础上,使用“经典”的机器学习模型和简单的单词袋方法来检测 state troll 推文。
我还将比较微调后的 Distilbert 模型与逻辑回归和 XGBoost 模型的结果,看看 transformer 模型在实际用例中是否真的表现得更好。
**剧透提示:**微调后的 transformer 模型的表现明显好于 Log-Reg 和 XGBoost 模型(当然,它们也不是没精打采的),并且在面对来自第三国的 state troll 推文时表现得更好。请跳到第 4 部分查看结果。
1.基础事实、数据来源、模型和回购
首先:我如何确定谁的推文被认为是国家影响力运动的作品?在这种情况下,地面真相是由 Twitter 的选举诚信团队建立的。
该项目中使用的 state troll 推文是那些已经由 Twitter识别并自 2018 年以来逐步向公众发布的推文。我从 Twitter 上选择了六组 state troll 推文——中国和俄罗斯各三条——我对它们进行了清理、合并,并缩减到 5 万行。
我通过使用 Tweepy 收集 175 个账户,创建了一组等价的 5 万行真实推文,这些账户由经过验证的用户和我亲自检查真实性的用户组成。由此产生的 100,000 行 state troll-plus-real tweets 的组合数据集被进一步分成通常的训练测试验证集,分别为 70:20:10 的标准比例。
完整的细节在我的笔记本里,为了简洁起见,我就不在这里重复了。此处提供完整回购。微调是在一个 Colab Pro 账户上完成的,花了大约五个半小时。
微调过的 Distilbert 模型对于 Github 来说太大了,但是我已经上传了一个副本到 Dropbox 上,供那些只想尝试这个模型的人使用。如果您希望创建一个更大的训练集,那么必须从 Twitter 下载包含 state troll tweets 的六个原始 CSV 文件。
2.数据准备
应该指出的是,数据清理和准备过程中的关键假设会影响结果。这些假设对于保持项目范围的实用性是必要的,但是如果您不同意这些假设,请同意根据您自己的首选清理规则对不同版本的数据进行切片。
我对这个项目的主要数据清理规则:
- 排除非英语推文,因为工作假设是目标受众是讲英语的。我还想防止模型根据语言做出预测。
- 排除转发。
- 排除文本清理后少于三个单词的推文。
出于实际原因,我还将最终的组合数据集保持在 100,000 行。我最初尝试用 600,000 行数据集对 Distilbert 进行微调,结果导致 Colab 笔记本反复崩溃和/或显示非常长且不切实际的运行时间。如果不能获得更多的计算/硬件,这个项目更雄心勃勃的版本是不切实际的。
3.使用自定义数据集微调 DISTILBERT 模型
对于这个项目,我选择了无壳蒸馏模型(更小,更容易管理),并使用拥抱脸的教练来完成任务。在运行了太长时间的几次尝试后,我放弃了尝试进行超参数搜索,并希望在未来的某一天回到这个主题(查看这里的讨论)。
所涉及的步骤相当简单,如我的回购的笔记本 2.0 中所述。代码大部分基于拥抱脸这里和这里的优秀例子和文档。
微调的直接结果当然令人印象深刻:
'eval_accuracy': 0.9158421345191773,
'eval_f1': 0.9163813100629625,
'eval_precision': 0.9098486510199605,
'eval_recall': 0.9230084557187361
我对验证集运行了一个快速测试——保留了 10,000 行,而模型根本没有看到*—*——优秀的分类指标几乎没有变化:
'eval_accuracy': 0.9179,
'eval_f1': 0.9189935865811544,
'eval_precision': 0.9178163184864012,
'eval_recall': 0.9201738786801027
为了进行更彻底的比较和分析,我使用用于微调 Distilbert 模型的相同数据集训练了两个独立的逻辑回归和 XGB 分类器模型。让我们看看他们在同样的测试中表现如何。
4.微调 DISTILBERT 与 LOG-REG 和 XGB
腌制的 Log-Reg 和 XGB 模型可以在我的 repo 的“pkl”文件夹中找到。我的笔记本详细记录了他们的优化过程,这里是,这里是。这里就不赘述了,只强调两个模型在训练和网格搜索中的得分都在 0.8 以上。虽然明显低于微调 Distilbert 模型的分数,但我认为这两个模型做得足够好,可以提供足够的比较。
下面的图表通过混淆矩阵显示了所有三个模型在验证集(10,000 行,包括 5,061 条 state troll 推文和 4,939 条真实推文)上的表现。
图片作者:蔡展汉
一眼看去,很明显,微调过的 Distilbert 模型(最左边)是表现最强的,比 Log-Reg 或 XGB 模型准确地挑选出了更多的状态 troll 和真实 tweets。更重要的是,Distilbert 模型的假阳性和假阴性数量大约是 log-reg 和 XGB 模型的一半。
因此,尽管这三个模型的性能指标似乎很接近,但通过混淆矩阵来看,它们的分类能力差距变得非常明显,这让我们更好地了解它们在分类成千上万条推文中的表现。
4.1 3 种型号的附加测试
所有三个模型都接受了来自中国和俄罗斯的真实推文和国家巨魔推文对半分的训练。事实上,我们并不知道 Twitter 上真人和巨魔的实际比例。更重要的是,state troll 推文可能来自任何国家,语气、语言和主题的变化可能会显著影响分类器将真实推文与来自国家支持的竞选活动的推文区分开来的能力。
如果暴露在来自第三国的国家巨魔推文中,这三个模型中的哪一个会保持得更好?为了找到答案,我通过三个模型运行了一个新的数据集——包括来自伊朗的 1000 条 troll 推文和来自美国用户的 993 条真实推文。这个新的数据集是从我在同一主题上做的早期项目中创建的。
图片作者:蔡展汉
正如所料,所有三个分类器在暴露于他们以前没有见过的伊朗国家巨魔推文时,他们的性能显著下降。
但在我看来,微调后的 Distilbert 模型仍然相当不错。与 Log-Reg 或 XGB 模型相比,它不仅正确地挑选出了更多的 troll 和真实推文,而且假阴性(模型认为是真实推文的 troll 推文)的数量也不是非常多。
这在 Log-Reg 模型中尤其成问题,该模型将一半(1000 条中的 501 条)的 troll 推文归类为真实推文,而实际上它们是由国家支持的运营商所为。XGB 模型在这方面稍好一些,但不是很好,假阴性的数量(468)明显高于假阳性的数量。
对于我在早期项目中训练的模型来说,这是一个特别明显的问题,这意味着在一个特定的州演员的 troll 推文中训练的分类器非常善于发现来自所述州演员的新的、看不见的推文。但是,一旦来自另一个国家运营商的 troll tweets 被注入混合,分类器的性能就会显著下降。
微调后的 Distilbert 模型并没有完全克服这个问题,但它足够好地支持了一个可以更好地“概括”的模型的希望。如果你有足够的计算资源在一个更大的数据集上训练一个 transformer 模型,这个数据集包括迄今为止 Twitter 识别的所有国家的 state troll tweets,那么有理由认为,上述模型可能在我们在这篇文章中尝试的测试中做得更好。
不幸的是,这是一个假设,我将不得不在另一个时间进行测试。
5.结论
当然,对 Twitter 上国家影响力活动的检测不仅仅包括对推文的审查。国家巨魔通常会留下更大的泄露秘密的迹象,比如账户创建的(协调)日期,或者他们发推的时间。照片和迷因的使用越来越多,也使得检测过程变得更加棘手。
但是在他们的推文中发现趋势和隐藏的结构将继续是一个主要的关注领域。与更流行的或传统的分类器相比,微调的 transformer 模型在这项任务中表现得更好。
当然,在资源和时间方面有所取舍。对大多数用户来说,在一百万行 tweets 上微调 transformer 模型所需的硬件并不容易获得,更不用说这是否是处理这项任务的最有效方式了。
6.奖励部分:网络应用
我尝试将微调后的 Distilbert 模型作为一个简单的 web 应用程序的一部分进行部署,但很快发现免费托管帐户没有足够的磁盘空间来在托管模型的基础上安装 pytorch。
但是我已经将必要的文件上传到 repo,以便任何想在本地机器上尝试的人使用。只要确保从 Dropbox 下载微调后的模型,并将其移动到“app”文件夹。
Gif 作者:蔡钦汉
和往常一样,如果你在这篇文章或我之前的文章中发现了错误,请联系我:
- 推特:蔡振鸿
- 领英:【www.linkedin.com/in/chuachinhon