Katakanlah Anda ingin skala rentang [min,max]
untuk [a,b]
. Anda sedang mencari fungsi (berkelanjutan) yang memuaskan
f(min) = a
f(max) = b
Dalam kasus Anda, a
akan menjadi 1 dan b
30, tetapi mari kita mulai dengan sesuatu yang lebih sederhana dan mencoba memetakan [min,max]
ke dalam rentang [0,1]
.
Dimasukkan min
ke dalam fungsi dan keluar 0 bisa dicapai dengan
f(x) = x - min ===> f(min) = min - min = 0
Jadi itulah yang kita inginkan. Tetapi menempatkan max
akan memberi kita max - min
ketika kita benar-benar ingin 1. Jadi kita harus skala itu:
x - min max - min
f(x) = --------- ===> f(min) = 0; f(max) = --------- = 1
max - min max - min
yang kami inginkan. Jadi kita perlu melakukan terjemahan dan penskalaan. Sekarang jika sebaliknya kita ingin mendapatkan nilai arbitrer dari a
dan b
, kita perlu sesuatu yang sedikit lebih rumit:
(b-a)(x - min)
f(x) = -------------- + a
max - min
Anda dapat memverifikasi bahwa menempatkan min
untuk x
sekarang memberi a
, dan memasukkan max
memberi b
.
Anda mungkin juga memperhatikan bahwa itu (b-a)/(max-min)
adalah faktor penskalaan antara ukuran rentang baru dan ukuran rentang asli. Jadi sebenarnya kita pertama menerjemahkan x
dengan -min
, penskalaan ke faktor yang benar, dan kemudian menerjemahkannya kembali ke nilai minimum baru a
.
Semoga ini membantu.
max != min
hasil fungsi yang tidak ditentukan :)min
negatif danmax
positif, atau apakah keduanya harus positif?Berikut ini beberapa JavaScript untuk kemudahan salin-rekat (ini jawaban menjengkelkan):
Diterapkan seperti itu, skala kisaran 10-50 ke kisaran antara 0-100.
Edit:
Saya tahu saya sudah menjawab ini sejak lama, tapi inilah fungsi pembersih yang saya gunakan sekarang:
Diterapkan seperti:
sumber
[1, 1, 1]
,[100, 100, 100]
atau bahkan[50.5, 50.5, 50.5]
. Anda dapat memasukkannya ke dalam case:if (max-min == 0) return this.map(num => (scaledMin+scaledMax)/2);
Untuk kenyamanan, berikut adalah algoritma Irritate dalam bentuk Java. Tambahkan pengecekan kesalahan, penanganan pengecualian dan penyesuaian yang diperlukan.
Penguji:
sumber
Begini cara saya memahaminya:
Persentase apa yang
x
ada dalam kisaranAnggaplah Anda memiliki rentang dari
0
hingga100
. Dengan nomor acak dari kisaran itu, "persen" berapa dari kisaran itu? Ini harus cukup sederhana,0
akan0%
,50
akan50%
dan100
akan terjadi100%
.Sekarang, bagaimana jika jangkauan Anda adalah
20
untuk100
? Kami tidak dapat menerapkan logika yang sama seperti di atas (bagi 100) karena:tidak memberi kita
0
(20
seharusnya0%
sekarang). Ini harus mudah diperbaiki, kita hanya perlu membuat pembilang0
untuk kasus20
. Kita bisa melakukannya dengan mengurangi:Namun, ini tidak berfungsi
100
lagi karena:tidak memberi kita
100%
. Sekali lagi, kita dapat memperbaikinya dengan mengurangi dari penyebut juga:Persamaan yang lebih digeneralisasi untuk mengetahui%
x
terletak pada rentang adalah:Rentang skala ke rentang lain
Sekarang kita tahu berapa persen angka yang berada dalam suatu rentang, kita dapat menerapkannya untuk memetakan angka ke rentang lain. Mari kita lihat sebuah contoh.
Jika kami memiliki nomor dalam rentang lama, berapakah angka tersebut dalam rentang baru? Katakanlah angkanya
400
. Pertama, cari tahu berapa persen400
dalam kisaran lama. Kita dapat menerapkan persamaan kita di atas.Jadi,
400
terletak pada25%
kisaran lama. Kami hanya perlu mencari tahu nomor berapa25%
dari kisaran baru. Pikirkan tentang apa50%
dari[0, 20]
yang. Apakah itu10
benar? Bagaimana Anda sampai pada jawaban itu? Baiklah, kita bisa melakukan:Tapi, bagaimana dengan dari
[10, 20]
? Kita perlu mengubah segalanya10
sekarang. misalnya:formula yang lebih umum adalah:
Untuk contoh asli apa
25%
dari[10, 20]
adalah:Jadi,
400
dalam kisaran[200, 1000]
akan memetakan ke12.5
dalam kisaran[10, 20]
TLDR
Untuk memetakan
x
dari rentang lama ke rentang baru:sumber
Saya menemukan solusi ini tetapi ini tidak benar-benar sesuai dengan kebutuhan saya. Jadi saya menggali sedikit dalam kode sumber d3. Saya pribadi akan merekomendasikan untuk melakukannya seperti halnya d3.scale.
Jadi di sini Anda mengukur domain ke kisaran. Keuntungannya adalah Anda dapat membalikkan tanda ke rentang target Anda. Ini berguna karena sumbu y pada layar komputer naik ke atas sehingga nilai-nilai besar memiliki y kecil.
Dan di sini adalah tes di mana Anda dapat melihat apa yang saya maksud
sumber
Saya telah mengambil jawaban Irritate dan mengembalikannya untuk meminimalkan langkah-langkah komputasi untuk perhitungan selanjutnya dengan memasukkannya ke dalam konstanta yang paling sedikit. Motivasinya adalah untuk memungkinkan scaler dilatih pada satu set data, dan kemudian dijalankan pada data baru (untuk algo ML). Efeknya, ini sangat mirip dengan MinMaxScaler preprocessing SciKit untuk Python dalam penggunaan.
Jadi,
x' = (b-a)(x-min)/(max-min) + a
(di mana b! = A) menjadix' = x(b-a)/(max-min) + min(-b+a)/(max-min) + a
yang dapat direduksi menjadi dua konstanta dalam bentukx' = x*Part1 + Part2
.Berikut ini adalah implementasi C # dengan dua konstruktor: satu untuk melatih, dan satu untuk memuat ulang instance yang terlatih (misalnya, untuk mendukung kegigihan).
sumber
Berdasarkan tanggapan Charles Clayton, saya memasukkan beberapa JSDoc, tweak ES6, dan memasukkan saran dari komentar dalam tanggapan asli.
sumber