本文介紹一種對紅細(xì)胞和白細(xì)胞圖像分類任務(wù)的主動學(xué)習(xí)端到端工作流程。
通過細(xì)胞圖像的標(biāo)簽對模型性能的影響,為數(shù)據(jù)設(shè)置優(yōu)先級和權(quán)重。 許多機(jī)器學(xué)習(xí)任務(wù)的主要障礙之一是缺乏標(biāo)記數(shù)據(jù)。而標(biāo)記數(shù)據(jù)可能會耗費(fèi)很長的時間,并且很昂貴,因此很多時候嘗試使用機(jī)器學(xué)習(xí)方法來解決問題是不合理的。 為了解決這個問題,機(jī)器學(xué)習(xí)領(lǐng)域出現(xiàn)了一個叫做主動學(xué)習(xí)的領(lǐng)域。主動學(xué)習(xí)是機(jī)器學(xué)習(xí)中的一種方法,它提供了一個框架,根據(jù)模型已經(jīng)看到的標(biāo)記數(shù)據(jù)對未標(biāo)記的數(shù)據(jù)樣本進(jìn)行優(yōu)先排序。 細(xì)胞成像的分割和分類等技術(shù)是一個快速發(fā)展的領(lǐng)域研究。就像在其他機(jī)器學(xué)習(xí)領(lǐng)域一樣,數(shù)據(jù)的標(biāo)注是非常昂貴的,并且對于數(shù)據(jù)標(biāo)注的質(zhì)量要求也非常的高。針對這一問題,本篇文章介紹一種對紅細(xì)胞和白細(xì)胞圖像分類任務(wù)的主動學(xué)習(xí)端到端工作流程。 我們的目標(biāo)是將生物學(xué)和主動學(xué)習(xí)的結(jié)合,并幫助其他人使用主動學(xué)習(xí)方法解決生物學(xué)領(lǐng)域中類似的和更復(fù)雜的任務(wù)。 本篇文主要由三個部分組成:
- 細(xì)胞圖像預(yù)處理——在這里將介紹如何預(yù)處理未分割的血細(xì)胞圖像。
- 使用CellProfiler提取細(xì)胞特征——展示如何從生物細(xì)胞照片圖像中提取形態(tài)學(xué)特征,以用作機(jī)器學(xué)習(xí)模型的特征。
- 使用主動學(xué)習(xí)——展示一個模擬使用主動學(xué)習(xí)和不使用主動學(xué)習(xí)的對比實(shí)驗。
細(xì)胞圖像預(yù)處理
我們將使用在MIT許可的血細(xì)胞圖像數(shù)據(jù)集(GitHub和Kaggle)。每張圖片都根據(jù)紅細(xì)胞(RBC)和白細(xì)胞(WBC)分類進(jìn)行標(biāo)記。對于這4種白細(xì)胞(嗜酸性粒細(xì)胞、淋巴細(xì)胞、單核細(xì)胞和中性粒細(xì)胞)還有附加的標(biāo)簽,但在本文的研究中沒有使用這些標(biāo)簽。 下面是一個來自數(shù)據(jù)集的全尺寸原始圖像的例子: ?創(chuàng)建樣本DF 原始數(shù)據(jù)集包含一個export.py腳本,它將XML注釋解析為一個CSV表,其中包含每個細(xì)胞的文件名、細(xì)胞類型標(biāo)簽和邊界框。 原始腳本沒有包含cell_id列,但我們要對單個細(xì)胞進(jìn)行分類,所以我們稍微修改了代碼,添加了該列并添加了一列包括image_id和cell_id的filename列:
裁剪 為了能夠處理數(shù)據(jù),第一步是根據(jù)邊界框坐標(biāo)裁剪全尺寸圖像。這就產(chǎn)生了很多大小不一的細(xì)胞圖像: ?裁剪的代碼如下:import os, sys, random
import xml.etree.ElementTree as ET
from glob import glob
import pandas as pd
from shutil import copyfile
annotations = glob('BCCD_Dataset/BCCD/Annotations/*.xml')
df = []
for file in annotations:
#filename = file.split('/')[-1].split('.')[0] + '.jpg'
#filename = str(cnt) + '.jpg'
filename = file.split('\')[-1]
filename =filename.split('.')[0] + '.jpg'
row = []
parsedXML = ET.parse(file)
cell_id = 0
for node in parsedXML.getroot().iter('object'):
blood_cells = node.find('name').text
xmin = int(node.find('bndbox/xmin').text)
xmax = int(node.find('bndbox/xmax').text)
ymin = int(node.find('bndbox/ymin').text)
ymax = int(node.find('bndbox/ymax').text)
row = [filename, cell_id, blood_cells, xmin, xmax, ymin, ymax]
df.append(row)
cell_id += 1
data = pd.DataFrame(df, columns=['filename', 'cell_id', 'cell_type', 'xmin', 'xmax', 'ymin', 'ymax'])
data['image_id'] = data['filename'].apply(lambda x: int(x[-7:-4]))
data[['filename', 'image_id', 'cell_id', 'cell_type', 'xmin', 'xmax', 'ymin', 'ymax']].to_csv('bccd.csv', index=False)
以上就是我們所做的所有預(yù)處理操作。現(xiàn)在,我們繼續(xù)使用CellProfiler提取特征。import os
import pandas as pd
from PIL import Image
def crop_cell(row):
"""
crop_cell(row)
given a pd.Series row of the dataframe, load row['filename'] with PIL,
crop it to the box row['xmin'], row['xmax'], row['ymin'], row['ymax']
save the cropped image,
return cropped filename
"""
input_dir = 'BCCDJPEGImages'
output_dir = 'BCCDcropped'
# open image
im = Image.open(f"{input_dir}{row['filename']}")
# size of the image in pixels
width, height = im.size
# setting the points for cropped image
left = row['xmin']
bottom = row['ymax']
right = row['xmax']
top = row['ymin']
# cropped image
im1 = im.crop((left, top, right, bottom))
cropped_fname = f"BloodImage_{row['image_id']:03d}_{row['cell_id']:02d}.jpg"
# shows the image in image viewer
# im1.show()
# save image
try:
im1.save(f"{output_dir}{cropped_fname}")
except:
return 'error while saving image'
return cropped_fname
if __name__ == "__main__":
# load labels csv into Pandas DataFrame
filepath = "BCCDdataset2-masterlabels.csv"
df = pd.read_csv(filepath)
# iterate through cells, crop each cell, and save cropped cell to file
dataset_df['cell_filename'] = dataset_df.apply(crop_cell, axis=1)
使用CellProfiler提取細(xì)胞特征
CellProfiler是一個免費(fèi)的開源圖像分析軟件,可以從大規(guī)模細(xì)胞圖像中自動定量測量。CellProfiler還包含一個GUI界面,允許我們可視化的操作。 首先下載CellProfiler,如果CellProfiler無法打開,則可能需要安裝Visual C ++發(fā)布包,具體安裝方式參考官網(wǎng)。 打開軟件就可以加載圖像了, 如果想構(gòu)建管道可以在CellProfiler官網(wǎng)找到其提供的可用的功能列表。大多數(shù)功能分為三個主要組:圖像處理,目標(biāo)的處理和測量。常用的功能如下: 圖像處理 - 轉(zhuǎn)為灰度圖: ?目標(biāo)對象處理 - 識別主要對象 ?測量 - 測量對象強(qiáng)度 ?CellProfiler可以將輸出為CSV文件或者保存指定數(shù)據(jù)庫中。這里我們將輸出保存為CSV文件,然后將其加載到Python進(jìn)行進(jìn)一步處理。 說明:CellProfiler還可以將你處理圖像的流程保存并進(jìn)行分享。
主動學(xué)習(xí)
我們現(xiàn)在已經(jīng)有了訓(xùn)練需要的搜有數(shù)據(jù),現(xiàn)在可以開始試驗使用主動學(xué)習(xí)策略是否可以通過更少的數(shù)據(jù)標(biāo)記獲得更高的準(zhǔn)確性。我們的假設(shè)是:使用主動學(xué)習(xí)可以通過大量減少在細(xì)胞分類任務(wù)上訓(xùn)練機(jī)器學(xué)習(xí)模型所需的標(biāo)記數(shù)據(jù)量來節(jié)省寶貴的時間和精力。 主動學(xué)習(xí)框架 在深入研究實(shí)驗之前,我們希望對modAL進(jìn)行快速介紹:modAL是Python的活躍學(xué)習(xí)框架。它提供了Sklearn API,因此可以非常容易地將其集成到代碼中。該框架可以輕松地使用不同的主動學(xué)習(xí)策略。他們的文檔也很清晰,所以建議從它開始你的一個主動學(xué)習(xí)項目。 主動學(xué)習(xí)與隨機(jī)學(xué)習(xí) 為了驗證假設(shè),我們將進(jìn)行一項實(shí)驗,將添加新標(biāo)簽數(shù)據(jù)的隨機(jī)子抽樣策略與主動學(xué)習(xí)策略進(jìn)行比較。開始用一些相同的標(biāo)記樣本訓(xùn)練2個Logistic回歸估計器。然后將在一個模型中使用隨機(jī)策略,在第二個模型中使用主動學(xué)習(xí)策略。 我們首先為實(shí)驗準(zhǔn)備數(shù)據(jù),加載由Cell Profiler創(chuàng)建的特征。這里過濾了無色血細(xì)胞的血小板,只保留紅和白細(xì)胞(將問題簡化,并減少數(shù)據(jù)量) 。所以現(xiàn)在我們正在嘗試解決二進(jìn)制分類問題 - RBC與WBC。使用Sklearn Label的label encoder進(jìn)行編碼,并拆分?jǐn)?shù)據(jù)集進(jìn)行訓(xùn)練和測試。
下一步就是創(chuàng)建模型:# imports for the whole experiment
import numpy as np
from matplotlib import pyplot as plt
from modAL import ActiveLearner
import pandas as pd
from modAL.uncertainty import uncertainty_sampling
from sklearn import preprocessing
from sklearn.metrics import , average_precision_score
from sklearn.linear_model import LogisticRegression
# upload the cell profiler features for each cell
data = pd.read_csv('Zaretski_Image_All.csv')
# filter platelets
data = data[data['cell_type'] != 'Platelets']
# define the label
target = 'cell_type'
label_encoder = preprocessing.LabelEncoder()
y = label_encoder.fit_transform(data[target])
# take the learning features only
X = data.iloc[:, 5:]
# create training and testing sets
X_train, X_test, y_train, y_test = train_test_split(X.to_numpy(), y, test_size=0.33, random_state=42)
dummy_learner是使用隨機(jī)策略的模型,而active_learner是使用主動學(xué)習(xí)策略的模型。為了實(shí)例化一個主動學(xué)習(xí)模型,我們使用modAL包中的ActiveLearner對象。在“estimator”字段中,可以插入任何sklearnAPI兼容的模型。在query_strategy '字段中可以選擇特定的主動學(xué)習(xí)策略。這里使用“uncertainty_sampling()”。這方面更多的信息請查看modAL文檔。 將訓(xùn)練數(shù)據(jù)分成兩組。第一個是訓(xùn)練數(shù)據(jù),我們知道它的標(biāo)簽,會用它來訓(xùn)練模型。第二個是驗證數(shù)據(jù),雖然標(biāo)簽也是已知的但是我們假裝不知道它的標(biāo)簽,并通過模型預(yù)測的標(biāo)簽和實(shí)際標(biāo)簽進(jìn)行比較來評估模型的性能。然后我們將訓(xùn)練的數(shù)據(jù)樣本數(shù)設(shè)置成5。dummy_learner = LogisticRegression()
active_learner = ActiveLearner(
estimator=LogisticRegression(),
query_strategy=uncertainty_sampling()
)
我們訓(xùn)練298個epoch,在每個epoch中,將訓(xùn)練這倆個模型和選擇下一個樣本,并根據(jù)每個模型的策略選擇是否將樣本加入到我們的“基礎(chǔ)”數(shù)據(jù)中,并在每個epoch中測試其準(zhǔn)確性。因為分類是不平衡的,所以使用平均精度評分來衡量模型的性能。 在隨機(jī)策略中選擇下一個樣本,只需將下一個樣本添加到虛擬數(shù)據(jù)集的“新”組中,這是因為數(shù)據(jù)集已經(jīng)是打亂的的,因此不需要再進(jìn)行這個操作。對于主動學(xué)習(xí),將使用名為“query”的ActiveLearner方法,該方法獲取“新”組的未標(biāo)記數(shù)據(jù),并返回他建議添加到訓(xùn)練“基礎(chǔ)”組的樣本索引。被選擇的樣本都將從組中刪除,因此樣本只能被選擇一次。# the training size that we will start with
base_size = 5
# the 'base' data that will be the training set for our model
X_train_base_dummy = X_train[:base_size]
X_train_base_active = X_train[:base_size]
y_train_base_dummy = y_train[:base_size]
y_train_base_active = y_train[:base_size]
# the 'new' data that will simulate unlabeled data that we pick a sample from and label it
X_train_new_dummy = X_train[base_size:]
X_train_new_active = X_train[base_size:]
y_train_new_dummy = y_train[base_size:]
y_train_new_active = y_train[base_size:]
結(jié)果如下:# arrays to accumulate the scores of each simulation along the epochs
dummy_scores = []
active_scores = []
# number of desired epochs
range_epoch = 298
# running the experiment
for i in range(range_epoch):
# train the models on the 'base' dataset
active_learner.fit(X_train_base_active, y_train_base_active)
dummy_learner.fit(X_train_base_dummy, y_train_base_dummy)
# evaluate the models
dummy_pred = dummy_learner.predict(X_test)
active_pred = active_learner.predict(X_test)
# accumulate the scores
dummy_scores.append(average_precision_score(dummy_pred, y_test))
active_scores.append(average_precision_score(active_pred, y_test))
# pick the next sample in the random strategy and randomly
# add it to the 'base' dataset of the dummy learner and remove it from the 'new' dataset
X_train_base_dummy = np.append(X_train_base_dummy, [X_train_new_dummy[0, :]], axis=0)
y_train_base_dummy = np.concatenate([y_train_base_dummy, np.array([y_train_new_dummy[0]])], axis=0)
X_train_new_dummy = X_train_new_dummy[1:]
y_train_new_dummy = y_train_new_dummy[1:]
# pick next sample in the active strategy
query_idx, query_sample = active_learner.query(X_train_new_active)
# add the index to the 'base' dataset of the active learner and remove it from the 'new' dataset
X_train_base_active = np.append(X_train_base_active, X_train_new_active[query_idx], axis=0)
y_train_base_active = np.concatenate([y_train_base_active, y_train_new_active[query_idx]], axis=0)
X_train_new_active = np.concatenate([X_train_new_active[:query_idx[0]], X_train_new_active[query_idx[0] + 1:]], axis=0)
y_train_new_active = np.concatenate([y_train_new_active[:query_idx[0]], y_train_new_active[query_idx[0] + 1:]], axis=0)
?策略之間的差異還是很大的,可以看到主動學(xué)習(xí)只使用25個樣本就可以達(dá)到平均精度0.9得分!而使用隨機(jī)的策略則需要175個樣本才能達(dá)到相同的精度! 此外主動學(xué)習(xí)策略的模型的分?jǐn)?shù)接近0.99,而隨機(jī)模型的分?jǐn)?shù)在0.95左右停止了!如果我們使用所有數(shù)據(jù),那么它們最終分?jǐn)?shù)是相同的,但是我們的研究目的是在少量標(biāo)注數(shù)據(jù)的前提下訓(xùn)練,所以只使用了數(shù)據(jù)集中的300個隨機(jī)樣本。plt.plot(list(range(range_epoch)), active_scores, label='Active Learning')
plt.plot(list(range(range_epoch)), dummy_scores, label='Dummy')
plt.xlabel('number of added samples')
plt.ylabel('average precision score')
plt.legend(loc='lower right')
plt.savefig("models robustness vs dummy.png", bbox_inches='tight')
plt.show()
總結(jié)
本文展示了將主動學(xué)習(xí)用于細(xì)胞成像任務(wù)的好處。主動學(xué)習(xí)是機(jī)器學(xué)習(xí)中的一組方法,可根據(jù)其標(biāo)簽對模型性能的影響來優(yōu)先考慮未標(biāo)記的數(shù)據(jù)示例的解決方案。由于標(biāo)記數(shù)據(jù)是一項涉及許多資源(金錢和時間)的任務(wù),因此判斷那些標(biāo)記那些樣本可以最大程度地提高模型的性能是非常必要的。 細(xì)胞成像為生物學(xué),醫(yī)學(xué)和藥理學(xué)領(lǐng)域做出了巨大貢獻(xiàn)。以前分析細(xì)胞圖像需要有價值的專業(yè)人力資本,但是像主動學(xué)習(xí)這種技術(shù)的出現(xiàn)為醫(yī)學(xué)領(lǐng)域這種需要大量人力標(biāo)注數(shù)據(jù)集的領(lǐng)域提供了一個非常好的解決方案。 本文引用:
-
GitHub — Shenggan/BCCD_Dataset: BCCD (Blood Cell Count and Detection) Dataset is a small-scale dataset for blood cells detection.
-
Blood Cell Images | Kaggle
-
Active Learning in Machine Learning | by Ana Solaguren-Beascoa, PhD | Towards Data Science
-
Carpenter, A. E., Jones, T. R., Lamprecht, M. R., Clarke, C., Kang, I. H., Friman, O., … & Sabatini, D. M. (2006).
-
CellProfiler: image analysis software for identifying and quantifying cell phenotypes. Genome biology, 7(10), 1–11.
-
Stirling, D. R., Swain-Bowden, M. J., Lucas, A. M., Carpenter, A. E., Cimini, B. A., & Goodman, A. (2021).
審核編輯 :李倩
-
圖像分類
+關(guān)注
關(guān)注
0文章
90瀏覽量
11918 -
機(jī)器學(xué)習(xí)
+關(guān)注
關(guān)注
66文章
8418瀏覽量
132655 -
預(yù)處理
+關(guān)注
關(guān)注
0文章
33瀏覽量
10489
原文標(biāo)題:?細(xì)胞圖像數(shù)據(jù)的主動學(xué)習(xí)
文章出處:【微信號:vision263com,微信公眾號:新機(jī)器視覺】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。
發(fā)布評論請先 登錄
相關(guān)推薦
評論