机器学习

第一题

描述
1.What is overfitting? How to prevent overfitting (in both traditional method and deep learning)?
解答
过拟合是指的是模型在训练数据上表现非常好,但在未见过的测试数据上泛化能力较差。
传统机器学习方法中避免过拟合,可以采用以下方法:

  1. 交叉验证:将可用数据分成多个子集,在一个子集上训练模型,在其他子集上评估模型。
  2. l1和l2正则化:在损失函数中添加惩罚项,以抑制复杂或大参数值。
  3. 特征选择:选择仅对预测任务有重要贡献的最相关特征。剔除无关或冗余特征有助于减少过拟合。
  4. earlystopping:在训练过程中监控模型在验证集上的性能,在性能开始下降时停止训练过程。这可以防止模型过度优化训练数据。

在深度学习中避免过拟合方法:

  1. Dropout:在训练过程中随机丢弃部分神经元,以防止模型过度依赖特定的神经元
  2. 数据增强:通过对输入数据(图片)进行随机变换(如旋转、缩放或裁剪),增加训练数据集的大小,也可以用框架自带的Augment
  3. BatchNomolization:通过调整和缩放每个层的激活值来归一化神经网络的激活状态。减少内部协变量的偏移,稳定学习过程,可以防止过拟合。

    第二题

    描述
    混淆矩阵
    Show how to compute precision and recall from these four values.
    设想这样一个量化交易的预测任务,我们希望每个交易信号都尽量盈利。在这个任务里,我们首先需要优化的precision还是recall?为什么,请提供理由。
    设想这样一个风险预警任务。风险事件并不经常发生。我们十分害怕风险,希望躲过所有风险。我们需要每天提供预警信号。在这个任务里,我们首先需要优化的precision还是recall?为什么,请解释。
    解答
    Precision = TP/(TP+FP)
    Recall = TP/(TP+FN)
    Precision ,如果把盈利看为预测为正类别,则尽可能的少发生N的类别。
    风险预警任务中,不能错过任何可能的风险,需要更加关recall指标。
    chatgpt3.5
    在量化交易的预测任务中,我们应该优化precision而不是recall。Precision是指被预测为正例的样本中真正为正例的比例,而Recall是指所有真正为正例的样本中被正确预测为正例的比例。
    在量化交易中,我们希望每个交易信号都尽量盈利。因此,我们更关注被预测为正例的样本中真正为正例的比例,也就是盈利的比例。这意味着我们应该优化precision,以确保每个交易信号都有较高的盈利概率。
    对于风险预警任务,我们希望尽可能躲过所有风险。在这种情况下,我们更关注所有真正为正例的样本中被正确预测为正例的比例,也就是躲过风险的比例。因此,我们应该优化recall,以确保尽可能多的风险被正确预警。
    综上所述,在量化交易的预测任务中,我们应该优化precision,而在风险预警任务中,我们应该优化recall。

    第三题

    描述
    假设你做了一个机器学习模型上线了。每天业务部门产生很多数据,然后你的算法把这些数据进行收集,并制作成特征,然后通过机器学习算法进行预测。但是最近一个月你突然发现你的模型效果变差了很多。请写出你计划从哪些方面,运用何种数据分析或其他办法进行诊断。
    解答
  4. 首先通过numpy和matplot对训练数据和当前的数据的分布(包含各个属性的分布情况)进行分析;
  5. 判断是否突发事件影响(比如重大金融事件、自然灾害、数据源的属性发生变更等),如果不是则需要判断上限的机器学习模型是否存在过拟合现象,没有遇见过当前的数据,导致样本不足,需要重新进行训练
  6. 机器学习模型是否是时序模型,如果是依赖于状态转移,则需要定时更新模型
    chatgbt3.5
    当机器学习模型的性能下降时,下面是一些可以进行诊断的方面和方法:

  7. 数据的质量分析:首先,需要检查最近一个月的数据是否存在异常或缺失。可以使用数据可视化工具和统计方法来分析数据的分布、异常值以及缺失情况。如果发现数据质量问题,可能需要与业务部门合作,了解数据收集过程的变化,确保数据的一致性和完整性。

  8. 特征工程分析:特征是模型的输入,因此需要检查特征是否正确地进行收集和制作。可以使用特征重要性分析、相关系数和统计检验等方法来评估特征的质量和对目标变量的影响。如果发现特征存在问题,可能需要重新评估、筛选或创建新的特征。
  9. 模型分析:可以对模型进行详细的评估和分析,包括参数调优、模型选择和复杂度分析等。可以使用模型解释性技术如特征重要性、决策边界可视化等来理解模型对数据的拟合程度和预测能力。如果模型表现不佳,可以考虑尝试其他算法或模型结构。
  10. 时间分析:最近一个月模型性能下降可能与时间相关。可能需要检查是否存在季节性变化、趋势或突发事件等,这可能导致模型输出产生偏差。可以使用时间序列分析、周期性分析和异常检测等方法来识别这些因素。
  11. 环境变化:检查是否有环境变化,如操作系统、硬件、软件更新等。这些变化可能会影响模型的运行速度、稳定性和性能。确保模型运行环境的一致性,并与技术团队进行沟通以了解任何变化。
  12. 反馈机制:与业务部门和使用该模型的人员进行沟通,了解他们的反馈和观察。他们可能已经观察到了模型性能下降的迹象或有其他观察结果。这些反馈可以提供有关数据集、特征或模型的有用信息。
  13. A/B测试:如果可能,可以使用A/B测试来比较不同模型版本或参数配置的性能差异。通过对比测试集上的预测结果,可以评估不同模型版本之间的性能差异,并找出造成下降的具体因素。
    综合分析上述方面的结果,可以得出一些可能导致模型性能下降的原因,并根据诊断结果采取相应的措施,如数据清洗、特征调整、模型改进等,以提高模型的性能。

    第四题

    描述
    4.刚刚结束的美国大选中拜登获得了胜利。假设在大选开始之前,公司做了一个民调的网站,来抽样统计一下目前民主党和共和党的支持比例。但是公司有人后来发现访问这个网站的人70%是年轻人,其他年龄段也都有,但是相对比较少。这个比例和真实人口比例不同。另外还发现西海岸的州人数偏多,其他州人相对少,这个比例也和真实人口比例非常不同。假设年龄和州这两个特征是决定民主党和共和党支持比例的最重要因素。请设计一个合理的统计方法,能够更准确的估计美国全国人口真实的支持比例。
    解答
    由当前网站数据可以得出,网站参与人员主要以西海岸的州中70%的年轻人为主,另外年龄和州是选举的重要因素。
    1、从年龄进行考虑。
    1.1获得当前大选期间可以进行投票的全国人口年龄分布,设置不同的年龄bins进行分组,可以获得不同年龄的占比情况
    1.2基于网站不同投票情况进行各年龄段bins的统计,对比1.1全国各州人口年龄分布情况可以进行推算
    2.从州进行考虑
    2.1 获取近20年大选民主党和共和党对各州的选票情况(每个州的选票综合了人口数等),可以获得每个州对某个候选人的倾向程度
    2.2 从各个州的地理位置考虑,民主党和共和党候选人的选举法案分别倾向于不同的利益集团,从美国地图来看,西海岸的经济更加富裕,更倾向于某位候选人
    2.3 从各州参议院两个党派的人数进行考虑,党派人数较多的州,在政策宣传等方面更加倾向于该党派候选人
    总结:候选人的预测需要考虑每个州的地理位置、参议两院党派人数、历史上该州的投票情况、人口年龄分布、人口收入情况和候选人选举政策等因素。
    chatgbt3.5
    为了更准确地估计美国全国人口的支持比例,可以使用加权方法来调整网站访问者的样本数据,以反映真实人口比例。以下是一个合理的统计方法:
  14. 了解真实人口比例:获取关于美国人口年龄和州的分布数据,以便了解这两个特征在整个美国人口中的比例。可以参考相关统计机构或调查数据。
  15. 计算权重:根据真实人口比例和在网站样本数据中的比例差异,为每个样本分配一个权重。权重可以基于年龄和州两个特征进行计算。以年龄为例,可以计算每个年龄组在真实人口中的比例与在网站样本数据中的比例之间的差异,并将其作为权重应用于对应年龄组的样本。对于州的权重,也可以采用类似的方法。
  16. 加权估计支持比例:使用样本数据的权重,重新计算各年龄组和各州的支持比例,以得出更准确的估计。通过将每个样本的权重与对应的支持倾向(民主党或共和党)相乘,然后对所有样本进行加权平均,即可估计全国的民主党和共和党支持比例。
  17. 不确定性分析:在进行统计估计时,应考虑到估计结果的不确定性。可以使用统计方法(如置信区间)来估计支持比例的可信度范围或标准误差。这可以提供对估计结果的置信水平的量化信息。
    需要注意的是,此方法依赖于已有数据和真实人口比例的准确性。如果真实人口比例数据不可靠或陈旧,估计结果可能仍存在偏差。因此,建议尽量使用权威和最新的数据源进行准确的统计估计。

    算法

    第一题

    描述
    输入一个10进制数字,输出这个数8进制表示
    例子:
    输入: 10
    输出: 12
    测试输入:1000000
    思路分析
    模拟
    1
    2
    n = int(input())
    print(int(oct(n).split('0o')[-1]))

    第二题

    描述
    给定一个矩阵,找出从左上到右下角的一条路,使得这条路上数字和最大。这条路前进的方向只能向右或向下。输入的第一行是矩阵的行数和列数。输出第一行是一个序列,为该条路上的数字,第二行是这些数字的和。
    例子
    输入:
    3 3
    1 4 3
    2 3 1
    2 3 4
    输出
    1 4 3 3 4
    15

测试输入:
5 5
1 1 1 1 2
2 3 4 1 4
3 1 4 2 4
2 1 5 7 2
4 3 3 4 5
思路分析
二维dp+滚动数组+记忆路径

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
r,c = list(map(int,input().split()))
matrics = []
for i in range(r):
matrics.append(list(map(int,input().split())))

dp = [[0]*(c+1) for _ in range(r+1)]
d = dict()
for i in range(1,r+1):
for j in range(1,c+1):
if dp[i-1][j] > dp[i][j-1]:
dp[i][j] = dp[i-1][j]
d[(i,j)] = (i-1,j)
else:
dp[i][j] = dp[i][j-1]
d[(i,j)] = (i,j-1)
dp[i][j] += matrics[i-1][j-1]
res = []
start = d[(r,c)]
res.append(matrics[r-1][c-1])
while start != (1,1):
r,c = start
res.append(matrics[r-1][c-1])
start = d[(r,c)]
res.append(matrics[0][0])
print(' '.join([ str(_) for _ in res[::-1]]))
print(dp[-1][-1])

第三题

描述
3.一个自重复串是一个字符串,其前一半和后一半是一样的,例如 abcdbabcdb (长度一定是偶数)。输入一个字符串,找出其中最长的自重复子串。这里的子串要求连续。
例子
输入:
abababcdabcd
输出:
abcdabcd

测试输入:
faaacabcddcbabcddcbedfgaac
思路分析
暴力模拟

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# s = input()
# s = "abababcdabcd"
s = "faaacabcddcbabcddcbedfgaac"
n = len(s)
max_len = 1
start,end = 0,0
for i in range(n):
for j in range(i+1,n):
if (j-i+1)%2==0:
prefix = s[i:i+(j-i+1)//2]
suffix = s[i+(j-i+1)//2:Aj+1]
if prefix == suffix and j-i+1 > max_len:
max_len = j-i+1
start,end = i,j
print(s[start:end+1])

第四题

描述
输入一个无向图邻接矩阵A(Aij=1代表i点和j点相连,0代表不相连)。输出这个图的联通分量的个数(一个联通分量就是一个子图,该子图每两个点间都可以有路径到达)。输入第一行是这个图点的个数。
例子
输入:
5
0 1 1 0 0
1 0 1 0 0
1 1 0 0 0
0 0 0 0 1
0 0 0 1 0
输出
2
(注:该图有两个联通分量,一个是{1,2,3}, 一个是{4,5})
测试输入:
7
0 1 0 0 0 1 0
1 0 0 0 0 0 0
0 0 0 1 1 0 0
0 0 1 0 1 0 0
0 0 1 1 0 0 0
1 0 0 0 0 0 1
0 0 0 0 0 1 0
思路分析
并查集+注意更新最后每一个的fa节点

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
n = int(input())
matrics = []
for i in range(n):
matrics.append(list(map(int,input().split())))
# n = 5
# matrics = [[0, 1, 1, 0, 0],
# [1, 0, 1, 0, 0],
# [1, 1, 0, 0, 0],
# [0, 0, 0, 0, 1],
# [0, 0, 0, 1, 0]]

# 并查集代码
fa = [-1]*n
#初始化
for item in range(n):
fa[item] = item

def find(x:int):
if fa[x]!=x:
fa[x] = find(fa[x])
return fa[x]

def union(x:int,y:int):
a = find(x)
b = find(y)
if a!=b :
fa[b] = a
for i in range(n):
for j in range(i+1,n):
#存在一条边(i,j)(i < j)
if matrics[i][j]:
# print(i,j)
union(i,j)
print(len(set(fa)))

第五题

描述
5.有一个最大为5*6的0/1矩阵。你可以在矩阵里选一些位置(标红的位置),那么每个标红的位置包括该位置的上下左右的0、1都会翻转。如下例子:
原矩阵:
000000

000100
000100
000100
000000
新矩阵:
100000

110000
101010
000000
000000
现在输入一个0/1矩阵,请你写一个程序,确定需要选择哪些位置,恰好使得矩阵变成全0的矩阵。注意,如果1个位置被翻转多次,那么它是0或1取决于翻转次数的奇偶性,和翻转的循序无关。提示:我们有2组测试数据,一组比较小(26),可以通过穷举所有可能解决,另一组比较大(56),穷举时间不够。答对一组数据可以给一半分数。
输入:最大为5*6的0/1矩阵。
输出:和输入矩阵一样大的0/1矩阵,0代表没有选择该位置,1代表选择该位置
原矩阵:
001000
011101
001011
新矩阵:
000000
001000
000001
测试输入1
111011
010100
测试输入2
011010
100111
001001
100101
011100
思路分析
POJ1022
POJ1222熄灯问题 枚举算法 经典的位运算应用
枚举/高斯消元/位运算

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
def gusess(r,c):
for i in range(1,r):
for j in range(1,c+1):
p[i+1][j] = (matrics[i][j]+p[i][j]+p[i-1][j]+p[i][j-1]+p[i][j+1])%2
for j in range(1,c+1):
if(matrics[r][j] != (p[r][j-1]+p[r][j+1]+p[r][j]+p[r-1][j])%2):
return False
return True

# a = [[1,1,1,0,1,1],[0,1,0,1,0,0]]
# a = [[0,0,1,0,0,0],
# [0,1,1,1,0,1],
# [0,0,1,0,1,1]]
a = [[0,1,1,0,1,0],
[1,0,0,1,1,1],
[0,0,1,0,0,1],
[1,0,0,1,0,1],
[0,1,1,1,0,0]]

r = len(a)
c = len(a[0])
matrics = [[0]*(c+2) for _ in range(r+1)]
p = [[0]*(c+2) for _ in range(r+1)]

for i in range(1,r+1):
for j in range(1,c+1):
matrics[i][j] = a[i-1][j-1]
while gusess(r,c) == False:
p[1][1]+=1
k = 1
while p[1][k] > 1:
p[1][k] = 0
k+=1
p[1][k]+=1
for i in range(1,r+1):
t = []
for j in range(1,c+1):
t.append(p[i][j])
print(''.join([str(x) for x in t]))