我正在尝试为出现here的F#
代码构建Python
等效代码,我的代码如下:
let tripleExponentialSmoothing series slen alpha beta gamma nPreds =
let result : float list = []
let mutable smooth = 0.
let mutable trend = 0.
let seasonals = initialSeasonalComponents series 12
for i in 0..(series.Length+nPreds-1) do
match i with
| 0 -> // initial values
smooth <- series |> Array.head |> float
trend <- initialTrend series slen
result |> List.append [series |> Array.head |> float] |> ignore
| i when i >= series.Length -> // we are forecasting
let m = i - series.Length + 1
result |> List.append [(smooth + float m * trend) + seasonals.Item(i%slen)] |> ignore
| _ ->
let v = series |> Array.head |> float
let lastSmooth = smooth
smooth <- alpha*(v-seasonals.Item(i%slen)) + (1.-alpha)*(smooth+trend)
trend <- beta * (smooth-lastSmooth) + (1.-beta)*trend
seasonals.Item(i%slen) <- gamma*(v-smooth) + (1.-gamma)*seasonals.Item(i%slen)
result |> List.append [smooth + trend + seasonals.Item(i%slen)] |> ignore
result
我得到了以下错误:
警告FS0020:隐式忽略此表达式的结果。 考虑使用'ignore'明确地丢弃此值,例如“EXPR |&GT;忽略',或'让'将结果绑定到名称,例如'让结果= EXPR”。
我尝试将以上内容编写为以下Python
代码的转换:
def triple_exponential_smoothing(series, slen, alpha, beta, gamma, n_preds):
result = []
seasonals = initial_seasonal_components(series, slen)
for i in range(len(series)+n_preds):
if i == 0: # initial values
smooth = series[0]
trend = initial_trend(series, slen)
result.append(series[0])
continue
if i >= len(series): # we are forecasting
m = i - len(series) + 1
result.append((smooth + m*trend) + seasonals[i%slen])
else:
val = series[i]
last_smooth, smooth = smooth, alpha*(val-seasonals[i%slen]) + (1-alpha)*(smooth+trend)
trend = beta * (smooth-last_smooth) + (1-beta)*trend
seasonals[i%slen] = gamma*(val-smooth) + (1-gamma)*seasonals[i%slen]
result.append(smooth+trend+seasonals[i%slen])
return result
我做了什么错误,以及与提到的Python
相同的正确代码是什么。
答案 0 :(得分:4)
您正在运行for作为副作用。
也许你想要一个seq表达式,我认为在Python中你有生成器,但在F#中记住一切都是表达式。
let tripleExponentialSmoothing series slen alpha beta gamma nPreds =
let mutable smooth = 0.
let mutable trend = 0.
let seasonals = initialSeasonalComponents series 12 |> Dictionary
seq {
for i in 0..(series.Length+nPreds-1) do
match i with
| 0 -> // initial values
smooth <- series |> Array.head |> float
trend <- initialTrend series slen
yield series |> Array.head |> float
| i when i >= series.Length -> // we are forecasting
let m = i - series.Length + 1
yield (smooth + float m * trend) + seasonals.[i%slen]
| _ ->
let v = series |> Array.head |> float
let lastSmooth = smooth
smooth <- alpha*(v-seasonals.[i%slen]) + (1.-alpha)*(smooth+trend)
trend <- beta * (smooth-lastSmooth) + (1.-beta)*trend
seasonals.[i%slen] <- gamma*(v-smooth) + (1.-gamma)*seasonals.[i%slen]
yield smooth + trend + seasonals.[i%slen] }
因此,序列表达式的格式为seq { expr }
,并且在表达式中使用yield
来生成结果。
答案 1 :(得分:2)
正如在另一个答案中所提到的,你试图改变for
循环中的结果列表,但这是不可能的,因为默认情况下F#列表是不可变的。
如果您想直接遵循Python代码的样式,可以使用mutable ResizeArray
:
let tripleExponentialSmoothing series slen alpha beta gamma nPreds =
let result = ResizeArray<_>()
let mutable smooth = 0.
let mutable trend = 0.
let seasonals = initialSeasonalComponents series 12
for i in 0..(series.Length+nPreds-1) do
match i with
| 0 -> // initial values
smooth <- series |> Array.head |> float
trend <- initialTrend series slen
result.Add(series |> Array.head |> float)
| i when i >= series.Length -> // we are forecasting
let m = i - series.Length + 1
result.Add((smooth + float m * trend) + seasonals.Item(i%slen))
| _ ->
let v = series |> Array.head |> float
let lastSmooth = smooth
smooth <- alpha*(v-seasonals.Item(i%slen)) + (1.-alpha)*(smooth+trend)
trend <- beta * (smooth-lastSmooth) + (1.-beta)*trend
seasonals.Item(i%slen) <- gamma*(v-smooth) + (1.-gamma)*seasonals.Item(i%slen)
result.Add(smooth + trend + seasonals.Item(i%slen))
这不是非常惯用的F#代码,但它解决了您的直接问题。对于更实用的解决方案,您可以使用Gustavo提到的序列表达式并逐个生成结果,但您仍然将smooth
和trend
保留为可变变量,因此可能有更好的方法这样做 - 但如果不了解更多关于算法的信息,那很难猜到。