確かに、残りのファイル サイズを現在のダウンロード速度で割ることはできますが、ダウンロード速度が変動する場合 (変動する場合)、これはあまり良い結果にはなりません。よりスムーズなカウントダウンを生成するためのより良いアルゴリズムは何ですか?
6 に答える
これには指数移動平均が最適です。平均を平滑化して、新しいサンプルを追加するたびに、古いサンプルが全体的な平均に対して重要性を失うようにする方法を提供します。それらはまだ考慮されていますが、その重要性は指数関数的に低下します。また、これは「移動」平均であるため、保持する必要があるのは 1 つの数値だけです。
ダウンロード速度を測定する場合、式は次のようになります。
averageSpeed = SMOOTHING_FACTOR * lastSpeed + (1-SMOOTHING_FACTOR) * averageSpeed;
SMOOTHING_FACTOR
0 ~ 1 の数値です。この数値が大きいほど、古いサンプルが破棄される速度が速くなります。式でわかるように、SMOOTHING_FACTOR
is が 1 の場合は、最後の観測値を使用しているだけです。When SMOOTHING_FACTOR
is 0averageSpeed
は変わりません。したがって、適切なスムージングを得るには、通常は低い値が必要です。私は、0.005 が平均的なダウンロード速度に対してかなり良い平滑化値を提供することを発見しました。
lastSpeed
最後に測定されたダウンロード速度です。この値は、タイマーを約 1 秒ごとに実行して、最後に実行してからダウンロードしたバイト数を計算することで取得できます。
averageSpeed
は、明らかに、推定残り時間を計算するために使用する数値です。これを取得した最初のlastSpeed
測定値に初期化します。
speed=speedNow*0.5+speedLastHalfMinute*0.3+speedLastMinute*0.2
あなたができる最善のことは、残りのファイルサイズを平均ダウンロード速度で割ることです(これまでにダウンロードされたものを、ダウンロードしている時間で割ったものです)。これは最初は少し変動しますが、ダウンロードする時間が長くなるほど安定します。
Ben Dolman の回答は非常に役に立ちましたが、私のような数学にそれほど傾倒していない人にとっては、これをコードに完全に実装するのに約 1 時間かかりました。Pythonで同じことを言うより簡単な方法を次に示します。不正確な点がある場合はお知らせください。ただし、私のテストでは非常にうまく機能します。
def exponential_moving_average(data, samples=0, smoothing=0.02):
'''
data: an array of all values.
samples: how many previous data samples are avraged. Set to 0 to average all data points.
smoothing: a value between 0-1, 1 being a linear average (no falloff).
'''
if len(data) == 1:
return data[0]
if samples == 0 or samples > len(data):
samples = len(data)
average = sum(data[-samples:]) / samples
last_speed = data[-1]
return (smoothing * last_speed) + ((1 - smoothing) * average)
input_data = [4.5, 8.21, 8.7, 5.8, 3.8, 2.7, 2.5, 7.1, 9.3, 2.1, 3.1, 9.7, 5.1, 6.1, 9.1, 5.0, 1.6, 6.7, 5.5, 3.2] # this would be a constant stream of download speeds as you go, pre-defined here for illustration
data = []
ema_data = []
for sample in input_data:
data.append(sample)
average_value = exponential_moving_average(data)
ema_data.append(average_value)
# print it out for visualization
for i in range(len(data)):
print("REAL: ", data[i])
print("EMA: ", ema_data[i])
print("--")
Ben Dolman の回答を拡張して、アルゴリズム内の変動を計算することもできます。よりスムーズになりますが、平均速度も予測されます。
このようなもの:
prediction = 50;
depencySpeed = 200;
stableFactor = .5;
smoothFactor = median(0, abs(lastSpeed - averageSpeed), depencySpeed);
smoothFactor /= (depencySpeed - prediction * (smoothFactor / depencySpeed));
smoothFactor = smoothFactor * (1 - stableFactor) + stableFactor;
averageSpeed = smoothFactor * lastSpeed + (1 - smoothFactor) * averageSpeed;
変動があろうとなかろうと、予測と depencySpeed の適切な値を使用して、他のものと同じくらい安定しています。インターネットの速度に応じて、少し操作する必要があります。この設定は、0 から 1MB まで変動する平均速度 600 kB/s に最適です。