给定10个函数y=a+bx和1000个(x,y)数据点舍入为整型,如何导出10个最佳(a,b)元组

本文关键字:10个 整型 何导出 最佳 元组 舍入 1000个 a+bx 函数 数据 给定 | 更新日期: 2023-09-27 18:18:34

我们开发了一个软件,用来审计银行向接受信用卡和借记卡的商家收取的费用。我们的客户希望我们告诉他们信用卡处理器是否对他们收费过高。每笔交易的信用卡费用是这样计算的:

fee = fixed + variable*transaction_price

"收费方案"是一组信用卡使用的(fixed, variable)对,例如:好莱坞第一国民银行发行的万事达卡商业借记卡。我们相信在任何时候都有少于10种不同的收费方案在使用,但我们并没有从我们的合作伙伴那里得到一个完整的或当前的收费方案列表。(是的,我知道由于上限和其他陷阱,一些"费用方案"比上面的方程更复杂,但我们的交易已知只有a + bx方案在使用中)。

这是我们想要解决的问题:我们想要使用关于费用的每笔交易数据来导出正在使用的费用方案。然后,我们可以将该列表与每个客户应该根据其银行使用的收费方案进行比较。

我们得到的关于每个事务的数据是一个数据元组:(card_id, transaction_price, fee)

transaction_pricefee为整数分。银行为每笔交易滚动小数美分,直到累计大于1美分,然后将"四舍五入美分"附加到该交易的费用中。我们无法预测"舍入美分"将附属于哪笔交易。

card_id标识一组共享相同收费方案的卡。在典型的1万次交易中,可能会有几百个唯一的card_id。多个card_id将共享一个收费方案。

我们得到的数据是这样的,我们想要算出的是最后两列。

card_id    transaction_price       fee        fixed        variable
=======================================================================
12345      200                     22         ?            ?
67890      300                     21         ?            ?
56789      150                      8         ?            ?
34567      150                      8         ?            ?
34567      150    "rounding cent"-> 9         ?            ?
34567      150                      8         ?            ?

我们想要的最终结果是一个像这样的短列表,其中包含10个或更少的条目,显示最适合我们数据的收费方案。像这样:

fee_scheme_id       fixed     variable
======================================
1                      22            0
2                      21            0
3                       ?            ?
4                       ?            ?
...

平均费用约为8美分。这意味着四舍五入的美分有很大的影响,上面的推导需要大量的数据。

平均交易是125美分。交易价格总是在5美分的边界上。

我们想要一个简短的收费方案列表,"适合"98%以上的3000 +交易,每个客户每天得到。如果这些数据不足以达到98%的置信度,我们可以使用多天的数据。

由于在每个事务中都任意地使用了四舍五入的美分,所以这不是一个简单的代数问题。相反,这是一种统计聚类练习,我不确定如何解决。

对于如何处理这个问题有什么建议吗?实现可以是c#或T-SQL,根据给定的算法,哪个更有意义。

给定10个函数y=a+bx和1000个(x,y)数据点舍入为整型,如何导出10个最佳(a,b)元组

霍夫变换

从图像角度考虑问题:如果将输入数据绘制在价格与费用的图表上,则每个方案的条目将形成一条直线(四舍五入的美分是噪声)。将您的地块的密度图视为图像,任务简化为在图像中查找直线。这就是霍夫变换的作用

你基本上可以通过在可能的固定费用与可能的可变费用的图表中为每笔交易绘制一条线来解决这个问题,并在它们相交的地方添加线的值。在实际收费方案的点上,许多线将相交并形成一个大的局部最大值。通过检测这个最大值,您可以找到您的收费方案,甚至是收费方案的重要性程度。

这种方法肯定会起作用,但可能需要一些时间,这取决于您想要实现的分辨率。如果计算时间被证明是一个问题,请记住,粗糙霍夫空间的Voronoi图可以用作分类器-一旦您将点分类为收费方案,简单的线性回归就可以解决您的问题。

考虑到处理查询的存储需求与一天的事务数据的2次方相同,我假设这样的存储不是问题,因此:

  • 第一次:将每个card_id的交易按transaction_price分组,保留card_id、transaction_price和平均费用。这在SQL中很容易做到。这是假设,没有异常值-但如果需要,您可以在此阶段之后捕获这些异常值。生成的行数保证不高于原始数据点的数量。

  • 第二次:每组遍历这些新数据点(使用光标或c#)并计算b的平均值。在此阶段之后,如果需要,可以再次捕获任何异常值。

  • 第三遍:在b已知的情况下,每组计算a的平均值。这是基本的SQL。异常值总是

如果您决定在游标中执行第二步,则可以将所有这些都塞进存储过程中。

使用相同收费方案的不同card_id组现在可以通过以相同的精度四舍五入a和b并再次分组来合并到收费方案中(对不起,这是错误的单词,非英语母语)。

Hough转换是最通用的答案,尽管我不知道如何在SQL中实现它(而不是将数据提取出来并用您选择的通用语言处理它)。

唉,如果你有大量的输入数据(1000点是中等大小),如果你想要高精度的结果(尺度为size_of_the_input / (rho_precision * theta_precision)),那么天真的版本是很慢的。

有一种基于2^n-树的更快的方法,但是在网络上很少有直接插入的实现。(我最近在我参与的一个项目中用c++做了一个测试平台。也许我会把它整理一下,然后贴在某个地方。


如果数据有一些额外的顺序,你可能能够做得更好(即线段是否形成分段函数?)。


朴素霍夫变换

在(theta,rho)空间中定义一个累加器,跨度为[-pi,pi)和[0,max(斜边(x,y))],作为2d数组。

Foreach point in the input data
   Foreach bin in theta
      find the distance rho of the altitude from the origin to 
      a line through (a,y) and making angle theta with the horizontal
      rho = x cos(theta) + y sin(theta)
      and increment the bin (theta,rho) in the accumulator
Find the maximum bin in the accumulator, this 
represents the most line-like structure in the data
if (theta !=0) {a = rho/sin(theta); b = -1/tan(theta);}

在一次传递中可靠地获得多行需要更多的簿记,但并没有明显困难。

您可以通过平滑候选峰值附近的数据并拟合以获得子bin精度来稍微改进结果,这应该比使用较小的bin更快,并且应该相当平滑地拾取"四舍五入"美分的效果。

您将四舍五入的美分视为计算中一个重要的噪声来源,因此我将重点放在最小化该问题引起的噪声上。在我看来,最简单的方法就是增加样本量。

不要将数据视为数千个y=mx + b(+舍入),而是将数据分组为更大的子集:

如果你将X笔交易与相同的交易结合起来,并将其视为(X笔费用的总和)=(可变利率)*(X笔交易的总和)+ X(基本利率)(+舍入)你的舍入数字,那么噪音可能会被抛到一边。

得到足够的大小为'X'的组,你应该能够得到一个非常接近的实数的表示。