[數據競賽] 基於人工智能的分子篩選競賽思路,a榜十一,b榜第十

任務:
2014年,一種未知的疾病在全球肆虐,讓人類束手無策。致病蛋白質很多,它們的結構序列都藏在df_protein.csv 數據集中(Sequence特徵)。經過科學家的不懈努力,能與這些致病蛋白相結合的小分子(df_molecule.csv中的Fingerprint特徵表示了其結構)也被發現,並附上了它們的理化屬性。此外,在df_affinity.csv數據集中,包含了蛋白質和小分子之間的親和力數值(Ki特徵)。 時間緊迫!作爲算法科學家,你能夠僅僅在六週時間裏,從測試集(df_affinity_test_toBePredicted.csv)中預測出致病蛋白與小分子的親和力值,從而找出最有效的藥物分子嗎?

這次比賽的鏈接如下:http://www.dcjingsai.com/common/cmpt/%E5%9F%BA%E4%BA%8E%E4%BA%BA%E5%B7%A5%E6%99%BA%E8%83%BD%E7%9A%84%E8%8D%AF%E7%89%A9%E5%88%86%E5%AD%90%E7%AD%9B%E9%80%89_%E8%B5%9B%E4%BD%93%E4%B8%8E%E6%95%B0%E6%8D%AE.html


基於人工智能的分子篩選是一條關於迴歸類的題目,比賽的評估指標是mse,所以我們可以直接定義爲迴歸問題,數據爲小分子表和蛋白質表,這次我着重講解一下關於蛋白質方面的分析。

蛋白質表每條數據的長度都不一定相等,他是由二十種左右的氨基酸組成的一級序列結構。蛋白質一級結構序列解釋如下:
圖片: http://third.datacastle.cn//pkbigdata/master.other.img/ee78dbc6-5b10-4e43-a4a0-caaa48bfb42e.jpeg

蛋白質基礎特徵:
當我們看到中間每個氨基酸的定義的部分,他旁邊有各個氨基酸的特性,也就是疏水性,親水性,酸性,鹼性。蛋白質跟小分子作用是跟蛋白質本身的一些特性是息息相關的、這些可以作爲我們的統計特徵計算計算。代碼如下:

def close2water(item):
    close2water = ['G', 'Y', 'N', 'Q', 'S', 'T', 'C']
    return len([i for i in list(item) if i in close2water])

def away2water(item):
    away2water = ['A', 'V', 'L', 'I', 'F', 'W', 'M', 'P']
    return len([i for i in list(item) if i in away2water])

def sx(item):
    sx = ['D', 'E']
    return len([i for i in list(item) if i in sx])

def jx(item):
    jx = ['R', 'K', 'H']
    return len([i for i in list(item) if i in jx])

def fxx(item):
    fxx = ['F', 'W', 'Y', 'H']
    return len([i for i in list(item) if i in fxx])
...

如上是一些基本的蛋白質的基礎特徵,還有一些相對分子質量,消光係數等特徵我在競賽圈是已經開源的了。有了蛋白質的基本特徵,我們就可以開始構建我們的模型試試效果了。首先很感謝小伍哥的開源,我是站在了小伍哥開源的肩膀上做的比賽。所以我的模型就是lgb。lgb的使用有很多,我就不介紹了,大家不太清楚的可以看看網上lgb的使用方法。

數據劃分時候遇到的坑:
但是我們加了如上特徵的時候,分數是不太穩定的,所以應該是訓練集的劃分是有問題的
初步,我們隨機劃分了訓練測試集,這就導致了一個問題,我們的分數時好時不好,所以還是訓練集的劃分跟線上的分佈不太一致,因爲我用的是sklearn是0.18版本,所以是可以按照迴歸的y值來進行分層抽樣的,如果小夥伴們是0.19的話,可以按照蛋白質的類型去切分你們的數據集,這樣就可以把分數穩定下來了。
我花了大概70次左右的提交才發現了數據劃分的問題,當完成以上步驟的時候,我們的分數就差不多已經從0.134直接到0.131左右了。

蛋白質進階特徵:
蛋白質進階特徵,蛋白質是一串文本數值,按照常規分割就是3個一切,並且計算氨基酸的一些特性,我們通過w2v來計算每3個 氨基酸的相似性,這樣的話我們就可以找出一些近鄰的氨基酸的一些基礎特性。蛋白質的特性讓我們達到了0.128的分數。蛋白質一級結構序列可能含有一些非相似性的一些特徵, w2v的計算相似性的,我們通過計算不同切分的氨基酸的詞頻並且跟了lda模型構造了5個特徵,分別以不同的切分方式做了20個特徵,這讓我們從單模型0.125-0.124邁進。

# 蛋白質按照5切割
texts = [[word for word in re.findall(r'.{5}', document)]
         for document in list(protein_concat['Sequence'])]
cvs = []
for i in range(len(texts)):
    cvs = cvs + texts[i]

# 暫時準備用pca+cv做
from sklearn.feature_extraction.text import CountVectorizer
tfidf=CountVectorizer()
weight=tfidf.fit_transform(cvs)
print weight.shape[0], len(cvs)
del cvs
from sklearn.decomposition import LatentDirichletAllocation
lda = LatentDirichletAllocation(n_topics=5)
from sklearn.decomposition import PCA, NMF, TruncatedSVD
# nmf = NMF(n_components=3)
# pca = TruncatedSVD(n_components=5)
td = pd.DataFrame(lda.fit_transform(weight))
td.columns=["lda_{0}".format(i) for i in range(5)]
td["Protein_ID"] = pd.Series(protein_concat["Protein_ID"].values)
result1 = []
aa = list(protein_concat['Protein_ID'])
for i in range(len(texts)):
    result2 = []
    for w in range(len(texts[i])):
        result2.append(aa[i])
    result1.extend(result2)
td['Protein_ID'] = result1
del result1, result2

name = ["lda_{0}".format(i) for i in range(5)]
feat = pd.DataFrame(td.groupby(['Protein_ID'])[name].agg('mean')).reset_index()
print feat.shape
data = data.merge(feat, on='Protein_ID', how='left')
del td, weight
print "增加weight特徵"
print data.shape

小分子特徵:
小分子特徵我做的比較少,主要還是做了一些過濾篩選,fingerpoint這個特徵切分之後大概有128個特徵,但是有幾列特徵爲全0或者絕大多數是0的情況,這些的特徵給模型帶來了不好的影響,所以還對其中128列特徵做了過濾,代碼如下;

# 如果每列的和小於2000的話,那麼刪除這一列
drop = []for i in feat.columns:
    if np.sum(feat[i]) < 2000:
        drop.append(i)

然後就分別訓練了xgb和lgb的兩個模型,對兩個模型產生的結果做了一個加權平均,我們線上的成績就從0.124到0.123。

總結:
這次比賽最後2周決策失誤了,花了太多時間在stacking上面,但是stacking最終的效果沒有達到我的預期,可能是我的使用方式有些不太對,stacking還得加強一些看看。如果單模型能到123的話,應該還可以在提升一些名次。雖然這次比賽的前三名全部變了,但是不算問題太大,蛋白質的一些處理方式我覺得還可以在提升提升,比如計算tfidf,然後走pca。因爲這樣的話每個主要的蛋白質可能也會有提升,但是我沒有做嘗試,時間上面來不及,就放棄了。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章