ব্লক এনট্রপি গণনা করুন


12

আমি একবার একটি ফাংশন লিখতে হয়েছিল যা প্রদত্ত ব্লক আকারের জন্য প্রদত্ত প্রতীক সিরিজের ব্লক এনট্রপি গণনা করে ফলাফলটি কত সংক্ষিপ্ত হয়েছিল তা অবাক করে দিয়েছিলাম। এইভাবে আমি কোডগল্ফকে এমন একটি ফাংশন চ্যালেঞ্জ জানাতে চাই। আমি আপাতত (এবং কোন ভাষায়) আমি কী করেছি তা বলছি না, তবে কেউ যদি প্রথমে একই বা আরও ভাল ধারণা না নিয়ে আসে তবে আমি এক সপ্তাহ বা তার মধ্যে করব।

ব্লক এনট্রপি সংজ্ঞা:

একটি প্রতীক ক্রম A = A_1,…, A_n এবং একটি ব্লকের আকার এম দেওয়া হয়েছে:

  • মাপের একটি ব্লক হ'ল কোনও যথাযথ i এর জন্য চিহ্ন সিকোয়েন্সের ধারাবাহিক উপাদানগুলির অর্থাত্, এ_আই,…, এ_ (i + মি − 1) এর একটি বিভাগ।
  • যদি x মাপের এম এর প্রতীক ক্রম হয়, তবে এন (এক্স) এ এর ​​ব্লকের সংখ্যাকে বোঝায় যা এক্স এর সাথে সমান।
  • পি (এক্স) হ'ল সম্ভাবনা যা এ থেকে আসা একটি ব্লক আকারের মাপের প্রতীক ক্রমের সাথে মিল থাকে, অর্থাত, পি (এক্স) = এন (এক্স) / (এন − মি + 1)
  • পরিশেষে, এ এর ​​ব্লক আকারের এম এর ব্লক এনট্রপি হ'ল এলো (পি (এক্স)) এর সমস্ত ব্লকের এক্স এর আকারের এম বা (যা সমান) −p (x) · লগ (পি) এর যোগফল (x)) এটার আকারের প্রতিটি x এর উপরে মি। (আপনি যে কোনও যুক্তিসঙ্গত লোগারিদম পছন্দ করতে পারেন))

বিধিনিষেধ এবং স্পষ্টতা:

  • আপনার ক্রিয়াকলাপটি একটি আর্গুমেন্ট হিসাবে প্রতীক ক্রম A এর পাশাপাশি ব্লক আকারের এম গ্রহণ করা উচিত।
  • আপনি ধরে নিতে পারেন যে চিহ্নগুলি শূন্য-ভিত্তিক পূর্ণসংখ্যা হিসাবে বা অন্য কোনও সুবিধাজনক বিন্যাসে উপস্থাপিত হয়।
  • আপনার প্রোগ্রামটি তত্ত্বের ক্ষেত্রে কোনও যুক্তিসঙ্গত যুক্তি গ্রহণে সক্ষম হতে হবে এবং বাস্তবে একটি আদর্শ কম্পিউটারে উদাহরণ কেস (নীচে দেখুন) গণনা করতে সক্ষম হওয়া উচিত।
  • অন্তর্নির্মিত ফাংশন এবং লাইব্রেরিগুলিকে অনুমতি দেওয়া হয়, যতক্ষণ না তারা একটি কলটিতে প্রক্রিয়াটির বড় অংশগুলি সম্পাদন করে না, যেমন, A থেকে সমস্ত আকারের ব্লক বের করে, প্রদত্ত ব্লক এক্সের উপস্থিতিগুলির সংখ্যা গণনা করে বা এনট্রোপিগুলি গণনা করে পি মানগুলির ক্রম থেকে - আপনাকে সেগুলি নিজেই করতে হবে।

টেস্ট:

[2, 3, 4, 1, 2, 3, 0, 0, 3, 2, 3, 0, 2, 2, 4, 4, 4, 1, 1, 1, 0, 4, 1,
2, 2, 4, 0, 1, 2, 3, 0, 2, 3, 2, 3, 2, 0, 1, 3, 4, 4, 0, 2, 1, 4, 3,
0, 2, 4, 1, 0, 4, 0, 0, 2, 2, 0, 2, 3, 0, 0, 4, 4, 2, 3, 1, 3, 1, 1,
3, 1, 3, 1, 0, 0, 2, 2, 4, 0, 3, 2, 2, 3, 0, 3, 3, 0, 0, 4, 4, 1, 0,
2, 3, 0, 0, 1, 4, 4, 3]

এই ক্রমের প্রথম ব্লক এন্ট্রোপিগুলি হ'ল (প্রাকৃতিক লোগারিদমের জন্য):

  • মি = 1: 1.599
  • মি = 2: 3.065
  • মি = 3: 4.067
  • মি = 4: 4.412
  • মি = 5: 4.535
  • মি = 6: 4.554

@ m.buettner: আপনি আমার নিয়ম সংক্রান্ত আপনার সমাধান সীমান্তরেখা বিবেচনা, তাহলে আপনি এখনও এটা ব্যবহার করে দেখুন যায়নি - আমি সত্যিই শুধুমাত্র লাইন বরাবর সমাধান এড়াতে চান entropy(probabilities(blocks(A,m)))
Wrzlprmft

এটির জন্য লগ বেস 2 ব্যবহার করার রীতি কি নয়?
জোনাথন ভ্যান মাত্রে

শেষে এন্ট্রপির মানগুলি ধনাত্মক, তবে সম্ভাবনার লগারিদম negativeণাত্মক বা শূন্য। সুতরাং এনট্রপির সূত্রে একটি নেতিবাচক চিহ্নটি অনুপস্থিত।
হাইকো ওবারডিক

@ জোনাথনভান মাত্রে: আমি যতদূর জানি, এটি শৃঙ্খলার উপর নির্ভর করে যা লগারিদমের সবচেয়ে বেশি ব্যবহৃত হয়। যাইহোক, চ্যালেঞ্জের জন্য এটি এতটা গুরুত্বপূর্ণ নয় এবং এইভাবে আপনি যা চান বেসটি ব্যবহার করতে পারেন।
Wrzlprmft

@ হাইকো ওবারডিক: ধন্যবাদ, আমি তা ভুলে গেছি।
Wrzlprmft

উত্তর:


6

গণিত - 81 78 75 72 67 65 62 56 বাইট

আমি আগে ম্যাথমেটিকায় কিছু গল্ফ করিনি, সুতরাং আমি মনে করি উন্নতির জন্য আরও কিছু জায়গা আছে। এইটি নিয়ম Partitionএবং Tallyকার্যকারিতার কারণে যথেষ্ট পরিমাণে মেনে চলে না , তবে এটি বেশ ঝরঝরে তাই আমি ভেবেছিলাম যে আমি এটি যেভাবে পোস্ট করব।

f=N@Tr[-Log[p=#2/Length@b&@@@Tally[b=##~Partition~1]]p]&

এটি কোনও চিহ্নের সেট নিয়ে কাজ করে এবং এর মতো ব্যবহার করা যেতে পারে

sequence = {2, 3, 4, 1, 2, 3, 0, 0, 3, 2, 3, 0, 2, 2, 4, 4, 4, 1, 1, 
   1, 0, 4, 1, 2, 2, 4, 0, 1, 2, 3, 0, 2, 3, 2, 3, 2, 0, 1, 3, 4, 4, 
   0, 2, 1, 4, 3, 0, 2, 4, 1, 0, 4, 0, 0, 2, 2, 0, 2, 3, 0, 0, 4, 4, 
   2, 3, 1, 3, 1, 1, 3, 1, 3, 1, 0, 0, 2, 2, 4, 0, 3, 2, 2, 3, 0, 3, 
   3, 0, 0, 4, 4, 1, 0, 2, 3, 0, 0, 1, 4, 4, 3};
f[sequence, 3]

> 4.06663

এখানে কিছুটা অবারিত সংস্করণ দেওয়া হয়েছে:

f[sequence_, m_] := (
    blocks = Partition[sequence, m, 1];
    probabilities = Apply[#2/Length[blocks] &, Tally[blocks], {1}];
    N[Tr[-Log[probabilities]*probabilities]]
)

আমি সম্ভবত Nফলাফলের সাথে সরাসরি প্রয়োগ করলে এটি সম্ভবত দ্রুত চলবে Tally

যাইহোক, গাণিতিকের আসলে একটি Entropyফাংশন থাকে যা এটি 28 বাইটে হ্রাস করে , তবে এটি অবশ্যই নিয়মের বিপরীতে।

f=N@Entropy@Partition[##,1]&

অন্যদিকে, এখানে একটি 128 বাইট সংস্করণ রয়েছে যা পুনরায় সরবরাহ করে Partitionএবং Tally:

f=N@Tr[-Log[p=#2/n&@@@({#[[i;;i+#2-1]],1}~Table~{i,1,(n=Length@#-#2+1)}//.{p___,{s_,x_},q___,{s_,y_},r___}:>{p,{s,x+y},q,r})]p]&

Ungolfed:

f[sequence_, m_] := (
    n = Length[sequence]-m+1; (*number of blocks*)
    blocks = Table[{Take[sequence, {i, i+m-1}], 1},
                   {i, 1, n}];
    blocks = b //. {p___, {s_, x_}, q___, {s_, y_}, r___} :> {p,{s,x+y},q,r};
    probabilities = Apply[#2/n &, blocks, {1}];
    N[Tr[-Log[probabilities]*probabilities]]
)

Partitionএবং Tallyসীমান্তরেখার কেস নয়, তারা সরাসরি বিধিগুলি ভঙ্গ করছে, কারণ তারা "এ থেকে মাপের সমস্ত ব্লক বের করে নিচ্ছে" এবং "একটি প্রদত্ত ব্লক এক্স এর সংখ্যার সংখ্যা গণনা করছে", এক কল করে। তবুও, গাণিতিক সম্পর্কে আমি যা জানি, তার পরেও যদি কোনও শালীন সমাধান পাওয়া যায় তবে আমি অবাক হব না।
Wrzlprmft

1
@Wrzlprmft আমি এমন একটি গল্ফযুক্ত সংস্করণ যুক্ত করেছি যেখানে আমি পুনরায় সংশোধন করি Partitionএবং Tally
মার্টিন ইন্ডার

3

পার্ল, 140 বাইট

নিম্নলিখিত পার্ল স্ক্রিপ্টটি এমন একটি ফাংশন সংজ্ঞায়িত করে Eযা প্রতীক ক্রম গ্রহণ করে, সেগমেন্টের আকারের পরে আর্গুমেন্ট হিসাবে।

sub E{$m=pop;$E=0;%h=();$"=',';$_=",@_,";for$i(0..@_-$m){next
if$h{$s=",@_[$i..$i+$m-1],"}++;$E-=($p=s|(?=$s)||g/(@_-$m+1))*log$p;}return$E}

পরীক্ষার সাথে বর্ণহীন সংস্করণ

sub E { # E for "entropy"
    # E takes the sequence and segment size as arguments
    # and returns the calculated entropy.
    $m = pop;    # get segment size (last argument)
    $E = 0;      # initialize entropy
    %h = ();     # hash that remembers already calculated segments
    $" = ',';#"  # comma is used as separator
    $_ = ",@_,"; # $_ takes sequence as string, with comma as delimiters
    for $i (0 .. @_-$m) {
        $s = ",@_[$i..$i+$m-1],"; # segment
        next if$h{$s}++;          # check, if this segment is already calculated
        $p = s|(?=\Q$s\E)||g / (@_ - $m + 1); # calculate probability
             # N(x) is calculated using the substitution operator
             # with a zero-width look-ahead pattern
             # (golfed version without "\Q...\E", see below)
        $E -= $p * log($p); # update entropy
    }
    return $E
}

# Test

my @A = (
    2, 3, 4, 1, 2, 3, 0, 0, 3, 2, 3, 0, 2, 2, 4, 4, 4, 1, 1, 1, 0, 4, 1,
    2, 2, 4, 0, 1, 2, 3, 0, 2, 3, 2, 3, 2, 0, 1, 3, 4, 4, 0, 2, 1, 4, 3,
    0, 2, 4, 1, 0, 4, 0, 0, 2, 2, 0, 2, 3, 0, 0, 4, 4, 2, 3, 1, 3, 1, 1,
    3, 1, 3, 1, 0, 0, 2, 2, 4, 0, 3, 2, 2, 3, 0, 3, 3, 0, 0, 4, 4, 1, 0,
    2, 3, 0, 0, 1, 4, 4, 3
);

print "m = $_: ", E(@A, $_), "\n" for 1 .. @A;

ফলাফল:

m = 1: 1.59938036027528
m = 2: 3.06545141203611
m = 3: 4.06663334311518
m = 4: 4.41210802885304
m = 5: 4.53546705894451
m = 6: 4.55387689160055
m = 7: 4.54329478227001
m = 8: 4.53259949315326
m = 9: 4.52178857704904
...
m = 97: 1.38629436111989
m = 98: 1.09861228866811
m = 99: 0.693147180559945
m = 100: 0

প্রতীক:

চিহ্নগুলি পূর্ণসংখ্যার মধ্যে সীমাবদ্ধ নয়, কারণ স্ট্রিংয়ের উপর ভিত্তি করে প্যাটার্ন ম্যাচিং ব্যবহৃত হয়। প্রতীকটির স্ট্রিং প্রতিনিধিতে অবশ্যই কমা থাকতে হবে না কারণ এটি ডিলিমিটার হিসাবে ব্যবহৃত হয়। অবশ্যই, বিভিন্ন চিহ্নের বিভিন্ন স্ট্রিং উপস্থাপনা থাকতে হবে।

গল্ফযুক্ত সংস্করণে, প্রতীকগুলির স্ট্রিং প্রতিনিধিত্বগুলিতে নিদর্শনগুলির বিশেষ চরিত্রগুলি থাকা উচিত নয়। অতিরিক্ত চার বাইট \Q... \E সংখ্যার জন্য প্রয়োজন নেই।


1/4 খাটো সম্পর্কে হতে পারে: sub f{($s,$m,$r,%h)=@_;$h{x,@$s[$_..$_+$m-1]}++for 0..@$s-$m;$r-=($_/=@$s-$m+1)*log for values %h;return$r}; $sরেফারেন্সটি কোথায় , $rএবং প্রথম অ্যাসাইনমেন্টের সাথে অপরিবর্তিত%h পুনরায় সেট করা হয়েছে , তালিকাগুলি হ্যাশ কী (সামান্য সাহায্যে এবং কিছু - দুর্ভাগ্যক্রমে), এবং সাধারণভাবে কিছুটা কম জটিল বলে মনে হয়। $;x
ব্যবহারকারী 2846289

@ ভাদিমআর: চালাক! আমি প্রস্তাবিত উল্লেখযোগ্য পরিবর্তনগুলির কারণে, আপনি একটি উত্তর দিন। স্থানটির values %hপ্রয়োজন নেই, সুতরাং আপনার দ্রবণটির জন্য কেবল 106 বাইট দরকার।
হাইকো ওবারডিক

2

পাইথন 127 152 বি 138 বি

import math
def E(A,m):N=len(A)-m+1;R=range(N);return sum(math.log(float(N)/b) for b in [sum(A[i:i+m]==A[j:j+m] for i in R) for j in R])/N

আর কোনও নিয়ম ভঙ্গ না করার জন্য সামঞ্জস্য করা হয়েছে এবং কিছুটা সিউটার অ্যালগরিদম রয়েছে। আরও ছোট হতে সমন্বিত

পুরানো সংস্করণ:

import math
def E(A,m):
 N=len(A)-m+1
 B=[A[i:i+m] for i in range(N)]
 return sum([math.log(float(N)/B.count(b)) for b in B])/N

আমার প্রথম পাইথনের লিপি! এটি কর্মে দেখুন: http://pythonfiddle.com/entropy


এখনও পর্যন্ত দুর্দান্ত, তবে দুর্ভাগ্যক্রমে, countফাংশনটির ব্যবহারটি বিধি বিপরীতমুখী, যেহেতু এটি "প্রদত্ত ব্লকের এক্স এর সংখ্যার সংখ্যা গণনা করা"।
Wrzlprmft

এছাড়াও কিছু গল্ফিং টিপস: প্রথমটি একটিকে বাদ দিয়ে প্রতিটি লাইন ক্র্যাম করে কিছু অক্ষর সংরক্ষণ করতে পারেন (প্রয়োজনে পৃথক করুন ;)। এছাড়াও শেষ লাইনে বর্গাকার বন্ধনীগুলির প্রয়োজন নেই।
Wrzlprmft

চমৎকার উত্তর. আবার কিছু গল্ফিং টিপস: বুলিয়ান থেকে পূর্ণসংখ্যায় (অর্থাৎ and 1 or 0) সম্পূর্ণ রূপান্তর অপ্রয়োজনীয়। এছাড়াও, আপনি পূর্বনির্ধারিত করে কিছু অক্ষর সংরক্ষণ করতে পারেন range(N)
Wrzlprmft

1

নম্পির সাথে পাইথন, 146 143 বাইট

প্রতিশ্রুতি হিসাবে, এখানে আমার নিজস্ব সমাধান। এটি অ-নেতিবাচক পূর্ণসংখ্যার একটি ইনপুট প্রয়োজন:

from numpy import*
def e(A,m):
    B=zeros(m*[max(A)+1]);j=0
    while~len(A)<-j-m:B[tuple(A[j:j+m])]+=1;j+=1
    return -sum(x*log(x)for x in B[B>0]/j)

অসুবিধাটি হ'ল এটি বড় mবা এর জন্য আপনার স্মৃতি ফেটে max(A)

এখানে বেশিরভাগ অসম্পূর্ণ এবং মন্তব্য করা সংস্করণটি রয়েছে:

from numpy import *
def e(A,m):
    B = zeros(m*[max(A)+1])          # Generate (max(A)+1)^m-Array of zeroes for counting.
    for j in range(len(A)-m+1):
        B[tuple(A[j:j+m])] += 1      # Do the counting by directly using the array slice
                                     # for indexing.
    C = B[B>0]/(len(A)-m+1)          # Flatten array, take only non-zero entries,
                                     # divide for probability.
    return -sum(x*log(x) for x in C) # Calculate entropy

1

ম্যাটল্যাব

function E =BlockEntropy01(Series,Window,Base )

%-----------------------------------------------------------
% Calculates BLOCK ENTROPY of Series
% Series: a Vector of numbers
% Base: 2 or 10 (affects logarithm of the Calculation)
% for 2 we use log2, for 10 log10
% Windows: Length of the "Sliding" BLOCK
% E: Entropy
%-----------------------------------------------------------
% For the ENTROPY Calculations
% http://matlabdatamining.blogspot.gr/2006/....
% 11/introduction-to-entropy.html
% BlogSpot: Will Dwinnell
%-----------------------------------------------------------
% For the BLOCK ENTROPY
% http://codegolf.stackexchange.com/...
% questions/24316/calculate-the-block-entropy
%-----------------------------------------------------------
% Test (Base=10)
% Series=[2, 3, 4, 1, 2, 3, 0, 0, 3, 2, 3, 0, ....
%     2, 2, 4, 4, 4, 1, 1, 1, 0, 4, 1,2, 2, 4, 0, ....
%     1, 2, 3, 0, 2, 3, 2, 3, 2, 0, 1, 3, 4, 4, 0, ....
%     2, 1, 4, 3,0, 2, 4, 1, 0, 4, 0, 0, 2, 2, 0, ....
%     2, 3, 0, 0, 4, 4, 2, 3, 1, 3, 1, 1,3, 1, 3, 1, ....
%     0, 0, 2, 2, 4, 0, 3, 2, 2, 3, 0, 3, 3, 0, 0, 4, ...
%     4, 1, 0,2, 3, 0, 0, 1, 4, 4, 3]';
%
% Results 
%
% Window=1: 1.599
% Window=2: 3.065
% Window=3: 4.067
% Window=4: 4.412
% Window=5: 4.535
% Window=6: 4.554
%-----------------------------------------------------------
n=length(Series);
D=zeros(n,Window); % Pre Allocate Memory
for k=1:Window;    D(:,k)=circshift(Series,1-k);end
D=D(1:end-Window+1,:); % Truncate Last Part
%
% Repace each Row with a "SYMBOL"
% in this Case a Number ...............
[K l]=size(D);
for k=1:K; MyData(k)=polyval(D(k,:),Base);end
clear D
%-----------------------------------------------------------
% ENTROPY CALCULATIONS on MyData
% following  Will Dwinnell
%-----------------------------------------------------------
UniqueMyData = unique(MyData);
nUniqueMyData = length(UniqueMyData);
FreqMyData = zeros(nUniqueMyData,1); % Initialization
for i = 1:nUniqueMyData
    FreqMyData(i) = ....
        sum(double(MyData == UniqueMyData(i)));
end
% Calculate sample class probabilities
P = FreqMyData / sum(FreqMyData);
% Calculate entropy in bits
% Note: floating point underflow is never an issue since we are
%   dealing only with the observed alphabet
if Base==10
    E= -sum(P .* log(P));
elseif BASE==2
    E= -sum(P .* log2(P));
else
end
end

WITH TEST SCRIPT 
%-----------------------------------------------------------
Series=[2, 3, 4, 1, 2, 3, 0, 0, 3, 2, 3, 0, ....
    2, 2, 4, 4, 4, 1, 1, 1, 0, 4, 1,2, 2, 4, 0, ....
    1, 2, 3, 0, 2, 3, 2, 3, 2, 0, 1, 3, 4, 4, 0, ....
    2, 1, 4, 3,0, 2, 4, 1, 0, 4, 0, 0, 2, 2, 0, ....
    2, 3, 0, 0, 4, 4, 2, 3, 1, 3, 1, 1,3, 1, 3, 1, ....
    0, 0, 2, 2, 4, 0, 3, 2, 2, 3, 0, 3, 3, 0, 0, 4, ...
    4, 1, 0,2, 3, 0, 0, 1, 4, 4, 3]';
Base=10;
%-----------------------------------------------------------
for Window=1:6
    E =BlockEntropy01(Series,Window,Base )
end

3
পিপিসি.এসই তে স্বাগতম! এটি একটি কোড গল্ফ চ্যালেঞ্জ, যেখানে সম্ভব কয়েকটি অক্ষরে সমস্যা সমাধান করা লক্ষ্য। দয়া করে মন্তব্য, ন্যূনতম সাদা স্থান এবং একক-অক্ষর ভেরিয়েবলের নামগুলি (এবং আপনি যে কোনও শর্টকাট ভাবতে পারেন) পাশাপাশি সেই কোডটিতে বাইট সংখ্যা যুক্ত করুন।
মার্টিন ইন্ডার
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.