对于一个特定的基因评分系统,我希望设置一个基础图表,使得输入的新样本值根据多个基因测量值立即趋向于图表中的健康或不健康群体。假设我们有5个人,每个人测量了6个基因。
Import pandas as pdimport matplotlib.pyplot as pltimport numpy as npdf = pd.DataFrame(np.array([[A, 1, 1.2, 1.4, 2, 2], [B, 1.5, 1, 1.4, 1.3, 1.2], [C, 1, 1.2, 1.6, 2, 1.4], [D, 1.7, 1.5, 1.5, 1.5, 1.4], [E, 1.6, 1.9, 1.8, 3, 2.5], [F, 2, 2.2, 1.9, 2, 2]]), columns=['Gene', 'Healthy 1', 'Healthy 2', 'Healthy 3', 'Unhealthy 1', 'Unhealthy 2'])
这将创建以下表格:
Gene | Healthy 1 | Healthy 2 | Healthy 3 | Unhealthy 1 | Unhealthy 2 |
---|---|---|---|---|---|
A | 1.0 | 1.2 | 1.4 | 2.0 | 2.0 |
B | 1.5 | 1.0 | 1.4 | 1.3 | 1.2 |
C | 1.0 | 1.2 | 1.6 | 2.0 | 1.4 |
D | 1.7 | 1.5 | 1.5 | 1.5 | 1.4 |
E | 1.6 | 1.9 | 1.8 | 3.0 | 2.5 |
F | 2.0 | 2.2 | 1.9 | 2.0 | 2.0 |
然后,每个样本的X和Y坐标是通过将基因的贡献相加后计算得出的,每个基因的测量值乘以其参数/权重。头4个基因贡献Y值,而第5和第6个基因决定X值。wA – wF是与其基因A-F对应的参数/权重。
wA = .15 wB = .25wC = .35wD = .45wE = .50wF = .60n=0for n in range (5):y1 = df.iat[0,n]y2 = df.iat[1,n]y3 = df.iat[2,n]y4 = df.iat[3,n]TrueY = wA*y1+wB*y2+wC*y3+wD*y4x1 = df.iat[4,n]x2 = df.iat[5,n]TrueX = (wE*x1+wF*x2)result = (TrueX, TrueY)n += 1label = f"({TrueX},{TrueY})"plt.scatter(TrueX, TrueY, alpha=0.5)plt.annotate(label, (TrueX,TrueY), textcoords="offset points", xytext=(0,10), ha='center')
因此,我们计算所有坐标并绘制它们
现在我想知道如何优化wA-wF参数/权重,使得健康样本被推向图表的原点,比如(0.0),而不健康样本被推向一个合理的相反点,比如(1,1)。我已经研究了K-means/SVM,但作为一个初级程序员/生物化学家,我感到非常困惑,任何帮助都将不胜感激。
回答:
这是一个使用scipy.optimize
结合你的代码的示例。(由于你的代码包含一些语法和类型错误,我不得不进行了一些小的修正。)
import pandas as pdimport matplotlib.pyplot as pltimport numpy as npdf = pd.DataFrame(np.array([[1, 1.2, 1.4, 2, 2], [1.5, 1, 1.4, 1.3, 1.2], [1, 1.2, 1.6, 2, 1.4], [1.7, 1.5, 1.5, 1.5, 1.4], [1.6, 1.9, 1.8, 3, 2.5], [2, 2.2, 1.9, 2, 2]]), columns=['Healthy 1', 'Healthy 2', 'Healthy 3', 'Unhealthy 1', 'Unhealthy 2'], index=[['A', 'B', 'C', 'D', 'E', 'F']])wA = .15wB = .25wC = .35wD = .45wE = .50wF = .60from scipy.optimize import minimize# 使用给定的权重作为初始猜测w0 = np.array([wA, wB, wC, wD, wE, wF])# 要最小化的目标函数# - 它计算样本到(0,0)和(1,1)的距离的平方def fun(w): weighted = df.values*w[:, None] # 所有样本值乘以其权重 y = sum(weighted[:4]) # 计算所有5个"TrueY"坐标 x = sum(weighted[4:]) # 计算所有5个"TrueX"坐标 y[3:] -= 1 # 调整"Unhealthy"的y到目标(x,1) x[3:] -= 1 # 调整"Unhealthy"的x到目标(1,y) return sum(x**2+y**2) # 返回距离平方的和res = minimize(fun, w0)print(res)# 将优化后的权重重新分配给你的参数wA, wB, wC, wD, wE, wF = res.x# 这主要是你未更改的代码for n in range (5): y1 = df.iat[0,n] y2 = df.iat[1,n] y3 = df.iat[2,n] y4 = df.iat[3,n] TrueY = wA*y1+wB*y2+wC*y3+wD*y4 x1 = df.iat[4,n] x2 = df.iat[5,n] TrueX = (wE*x1+wF*x2) result = (TrueX, TrueY) label = f"({TrueX:.3f},{TrueY:.3f})" plt.scatter(TrueX, TrueY, alpha=0.5) plt.annotate(label, (TrueX,TrueY), textcoords="offset points", xytext=(0,10), ha='center')plt.savefig("mygraph.png")
这将产生参数[ 1.21773653, 0.22185886, -0.39377451, -0.76513658, 0.86984207, -0.73166533]
作为解决方案数组。由此我们可以看到健康样本聚集在(0,0)附近,而不健康样本聚集在(1,1)附近:
你可能想要尝试其他优化方法 – 见scipy.optimize.minimize
。