ঠিক আছে! ধারাবাহিকভাবে আমি নিয়মিত কিছু কাজ করতে সক্ষম হয়েছি! এই সমস্যাটি আমাকে বেশ কয়েকদিন ধরে টানতে ... মজাদার জিনিস! এই উত্তরের দৈর্ঘ্যের জন্য দুঃখিত, তবে কয়েকটি বিষয় সম্পর্কে আমার কিছুটা বিস্তারিত জানানো দরকার ... (যদিও আমি স্প্যামের দীর্ঘতম অ-স্ট্যাকওভারফ্লো উত্তরটি রেকর্ড করতে পারি!)
পার্শ্ব দ্রষ্টব্য হিসাবে, আমি পূর্ণ ডেটাসেট ব্যবহার করছি যা আইভো তার মূল প্রশ্নের একটি লিঙ্ক সরবরাহ করেছিল । এটি রার ফাইলগুলির একটি সিরিজ (এক-প্রতি-কুকুর) যার মধ্যে বেশ কয়েকটি বিভিন্ন পরীক্ষামূলক রান রয়েছে যা এসকিআই অ্যারে হিসাবে সংরক্ষণ করা হয়। এই প্রশ্নের মধ্যে একক কোড উদাহরণগুলি অনুলিপি করার চেষ্টা করার পরিবর্তে, এখানে সম্পূর্ণ, একা একা কোড সহ একটি বিটবাকেট পার্কিয়াল সংগ্রহস্থল । আপনি এটি দিয়ে ক্লোন করতে পারেন
hg clone https://joferkington@bitbucket.org/joferkington/paw-analysis
সংক্ষিপ্ত বিবরণ
সমস্যাটি দেখার জন্য মূলত দুটি উপায় রয়েছে, যেমন আপনি আপনার প্রশ্নে উল্লেখ করেছেন। আমি উভয়ই বিভিন্ন উপায়ে ব্যবহার করতে যাচ্ছি।
- কোন পাটি কোনটি তা নির্ধারণ করতে পাঞ্জা প্রভাবগুলির (অস্থায়ী এবং স্থানিক) ক্রমটি ব্যবহার করুন।
- খাঁটি আকারের উপর ভিত্তি করে "পাউপ্রিন্ট" সনাক্ত করার চেষ্টা করুন।
মূলত, কুকুরটির পাঞ্জা দিয়ে প্রথম পদ্ধতিটি আইভোর প্রশ্নের উপরে বর্ণিত ট্র্যাপিজয়েডাল-জাতীয় প্যাটার্নটি অনুসরণ করে, কিন্তু যখনই পাঞ্জা সেই প্যাটার্নটি অনুসরণ করে না তখন ব্যর্থ হয়। যখন এটি কাজ করে না তখন প্রোগ্রামোগুলিভাবে সনাক্ত করা মোটামুটি সহজ।
অতএব, আমরা কোন পরিমাপটি ব্যবহার করতে পারি যেখানে এটি কোন পাঞ্জাটি চিহ্নিত করার জন্য একটি প্রশিক্ষণ ডেটাসেট (~ 30 বিভিন্ন কুকুরের থেকে 2000 পাউন্ডের প্রভাবগুলির) তৈরি করতে কাজ করেছে এবং সমস্যাটি তদারক করা শ্রেণিবিন্যাসে হ্রাস পেয়েছে (কিছু অতিরিক্ত চুলকানির সাহায্যে)। .. "স্বীকৃত" শ্রেণিবিন্যাস সমস্যার তুলনায় চিত্রের স্বীকৃতি কিছুটা শক্ত)
প্যাটার্ন বিশ্লেষণ
প্রথম পদ্ধতির বিশদটি জানাতে, যখন একটি কুকুর সাধারণত হাঁটতে থাকে (চালাচ্ছে না!) (এই কুকুরগুলির মধ্যে কিছু নাও থাকতে পারে), আমরা প্রত্যাশা করি পাঞ্জাবির ক্রমটি প্রভাবিত হবে: ফ্রন্ট বাম, হিন্দ রাইট, ফ্রন্ট রাইট, হিন্দ বাম , সম্মুখ বাম, ইত্যাদি প্যাটার্নটি সামনের বাম বা সামনের ডান পা দিয়ে শুরু করা যেতে পারে।
যদি এটি সর্বদা হয়, তবে আমরা প্রাথমিক যোগাযোগের সময়গুলি দ্বারা কেবল প্রভাবগুলি সাজিয়ে রাখতে পারি এবং পাঞ্জা দিয়ে তাদের গ্রুপ করার জন্য একটি মডিউল 4 ব্যবহার করতে পারি।
যাইহোক, সবকিছু "স্বাভাবিক" হলেও, এটি কার্যকর হয় না। এটি প্যাটার্নের ট্র্যাপিজয়েড-জাতীয় আকৃতির কারণে। একটি পূর্ববর্তী পা sp
অতএব, প্রারম্ভিক সামনের পাঞ্জা প্রভাব পরে পশম পাঞ্জাব প্রভাব প্রায়শই সেন্সর প্লেট থেকে পড়ে এবং রেকর্ড হয় না। একইভাবে, শেষ পাজ প্রভাবটি সেন্সর প্লেটটি বন্ধ হয়ে যাওয়ার আগে এবং পাথর রেকর্ড করা না হওয়ার আগে পর্বের প্রভাব হিসাবে প্রায়শই পরের পাঞ্জা নয়।
তা সত্ত্বেও, আমরা কখনই এটি ঘটেছে তা নির্ধারণ করতে এবং আমরা বাম বা ডান সামনের পাঞ্জা দিয়ে শুরু করেছি কিনা তা নির্ধারণের জন্য পাঞ্জাব প্রভাব প্রভাবের আকার ব্যবহার করতে পারি। (আমি আসলে এখানে সর্বশেষ প্রভাব নিয়ে সমস্যাগুলি উপেক্ষা করছি it এটি যুক্ত করা খুব বেশি কঠিন নয়))
def group_paws(data_slices, time):
# Sort slices by initial contact time
data_slices.sort(key=lambda s: s[-1].start)
# Get the centroid for each paw impact...
paw_coords = []
for x,y,z in data_slices:
paw_coords.append([(item.stop + item.start) / 2.0 for item in (x,y)])
paw_coords = np.array(paw_coords)
# Make a vector between each sucessive impact...
dx, dy = np.diff(paw_coords, axis=0).T
#-- Group paws -------------------------------------------
paw_code = {0:'LF', 1:'RH', 2:'RF', 3:'LH'}
paw_number = np.arange(len(paw_coords))
# Did we miss the hind paw impact after the first
# front paw impact? If so, first dx will be positive...
if dx[0] > 0:
paw_number[1:] += 1
# Are we starting with the left or right front paw...
# We assume we're starting with the left, and check dy[0].
# If dy[0] > 0 (i.e. the next paw impacts to the left), then
# it's actually the right front paw, instead of the left.
if dy[0] > 0: # Right front paw impact...
paw_number += 2
# Now we can determine the paw with a simple modulo 4..
paw_codes = paw_number % 4
paw_labels = [paw_code[code] for code in paw_codes]
return paw_labels
এত কিছুর পরেও এটি প্রায়শই সঠিকভাবে কাজ করে না। পুরো ডেটাসেটের অনেকগুলি কুকুর দৌড়াদৌড়ি করে দেখা যায় এবং পা এর প্রভাবগুলি কুকুরটির হাঁটাচলা করার সময় একই অস্থায়ী আদেশ অনুসরণ করে না। (অথবা সম্ভবত কুকুরটির কেবল হিপ সমস্যা রয়েছে ...)
ভাগ্যক্রমে, আমরা এখনও পাগলের প্রভাবগুলি আমাদের প্রত্যাশিত স্থানিক প্যাটার্নটি অনুসরণ করে কিনা তা প্রগতিগতভাবে সনাক্ত করতে পারি:
def paw_pattern_problems(paw_labels, dx, dy):
"""Check whether or not the label sequence "paw_labels" conforms to our
expected spatial pattern of paw impacts. "paw_labels" should be a sequence
of the strings: "LH", "RH", "LF", "RF" corresponding to the different paws"""
# Check for problems... (This could be written a _lot_ more cleanly...)
problems = False
last = paw_labels[0]
for paw, dy, dx in zip(paw_labels[1:], dy, dx):
# Going from a left paw to a right, dy should be negative
if last.startswith('L') and paw.startswith('R') and (dy > 0):
problems = True
break
# Going from a right paw to a left, dy should be positive
if last.startswith('R') and paw.startswith('L') and (dy < 0):
problems = True
break
# Going from a front paw to a hind paw, dx should be negative
if last.endswith('F') and paw.endswith('H') and (dx > 0):
problems = True
break
# Going from a hind paw to a front paw, dx should be positive
if last.endswith('H') and paw.endswith('F') and (dx < 0):
problems = True
break
last = paw
return problems
অতএব, যদিও সাধারণ স্থানিক শ্রেণিবিন্যাস সমস্ত সময় কাজ করে না, আমরা কখন তা যুক্তিযুক্ত আত্মবিশ্বাসের সাথে কাজ করে তা নির্ধারণ করতে পারি।
প্রশিক্ষণ ডেটাসেট
প্যাটার্ন-ভিত্তিক শ্রেণিবিন্যাস থেকে যেখানে এটি সঠিকভাবে কাজ করেছে, আমরা সঠিকভাবে শ্রেণিবদ্ধ পাঞ্জার একটি খুব বড় প্রশিক্ষণের ডেটাসেট তৈরি করতে পারি (32 টি কুকুরের কাছ থেকে 2400 পাউন্ডের প্রভাব!)।
আমরা এখন "গড়" সামনের বাম, ইত্যাদি কীভাবে দেখায় তা দেখতে শুরু করতে পারি।
এটি করার জন্য, আমাদের কিছু ধরণের "পা ম্যাট্রিক" দরকার যা কোনও কুকুরের জন্য একই মাত্রিকতা। (পুরো ডেটাসেটে, খুব বড় এবং খুব ছোট কুকুর উভয়ই রয়েছে!) আইরিশ এলখাউন্ডের একটি পাঞ্জাবি মুদ্রণ খেলনা পোডলের পাঞ্জা মুদ্রণের চেয়ে অনেক বেশি বিস্তৃত এবং অনেক "ভারী" হবে। আমাদের প্রতিটি পা প্রিন্ট পুনরুদ্ধার করতে হবে যাতে ক) তাদের একই সংখ্যক পিক্সেল থাকে এবং খ) চাপ মানগুলি মানক করা হয়। এটি করার জন্য, আমি প্রতিটি পা প্রিন্টকে 20x20 গ্রিডে পুনরায় তৈরি করেছি এবং পাঞ্জা প্রভাবের জন্য সর্বাধিক, মিনিমাম এবং গড় চাপের মানের উপর ভিত্তি করে চাপ মানগুলি উদ্ধার করেছি।
def paw_image(paw):
from scipy.ndimage import map_coordinates
ny, nx = paw.shape
# Trim off any "blank" edges around the paw...
mask = paw > 0.01 * paw.max()
y, x = np.mgrid[:ny, :nx]
ymin, ymax = y[mask].min(), y[mask].max()
xmin, xmax = x[mask].min(), x[mask].max()
# Make a 20x20 grid to resample the paw pressure values onto
numx, numy = 20, 20
xi = np.linspace(xmin, xmax, numx)
yi = np.linspace(ymin, ymax, numy)
xi, yi = np.meshgrid(xi, yi)
# Resample the values onto the 20x20 grid
coords = np.vstack([yi.flatten(), xi.flatten()])
zi = map_coordinates(paw, coords)
zi = zi.reshape((numy, numx))
# Rescale the pressure values
zi -= zi.min()
zi /= zi.max()
zi -= zi.mean() #<- Helps distinguish front from hind paws...
return zi
এত কিছুর পরেও, আমরা অবশেষে একবারে গড় বাম সম্মুখ, ডানদিকের ডানদিক ইত্যাদির পাঞ্জা দেখতে কেমন তা একবার দেখে নিই। নোট করুন যে এটির গড় গড়> বেশ কয়েকটি আকারের 30 টি কুকুর, এবং আমরা মনে হয় ধারাবাহিক ফলাফল পাচ্ছি!
যাইহোক, এগুলি সম্পর্কে কোনও বিশ্লেষণ করার আগে আমাদের গড়টি (সকল কুকুরের সমস্ত পায়ে গড় পাঞ্জা) বিয়োগ করতে হবে।
এখন আমরা গড় থেকে পার্থক্যগুলি বিশ্লেষণ করতে পারি, যা সনাক্ত করা কিছুটা সহজ:
চিত্র-ভিত্তিক পা স্বীকৃতি
ঠিক আছে ... শেষ পর্যন্ত আমাদের কাছে এমন একটি নিদর্শন রয়েছে যা আমরা পাঞ্জাগুলির সাথে ম্যাচ করার চেষ্টা করতে শুরু করতে পারি। প্রতিটি পাজকে 400-মাত্রিক ভেক্টর হিসাবে বিবেচনা করা যেতে পারে ( paw_image
ফাংশন দ্বারা ফিরে ) যা এই চারটি-মাত্রিক ভেক্টরগুলির সাথে তুলনা করা যেতে পারে।
দুর্ভাগ্যক্রমে, আমরা যদি কেবলমাত্র "সাধারণ" তত্ত্বাবধানযুক্ত শ্রেণিবদ্ধকরণ অ্যালগরিদম ব্যবহার করি (অর্থাত্ 4 টি নিদর্শনগুলির মধ্যে কোনটি একটি সাধারণ দূরত্ব ব্যবহার করে কোনও নির্দিষ্ট পা প্রিন্টের নিকটবর্তী এটি সন্ধান করুন), এটি ধারাবাহিকভাবে কাজ করে না। প্রকৃতপক্ষে, প্রশিক্ষণ ডেটাসেটে এলোমেলো সুযোগের চেয়ে এটি আরও ভাল কিছু করে না।
এটি চিত্রের স্বীকৃতিতে একটি সাধারণ সমস্যা। ইনপুট ডেটার উচ্চ মাত্রিকতার কারণে, এবং কিছুটা "अस्पष्ट" প্রকৃতির চিত্রগুলির (যেমন সংলগ্ন পিক্সেলগুলির উচ্চতর সমবায় রয়েছে), কেবলমাত্র একটি টেমপ্লেট চিত্র থেকে একটি চিত্রের পার্থক্য তাকানো একটি খুব ভাল পরিমাপ দেয় না তাদের আকারের মিল।
Eigenpaws
এটি ঘুরে দেখার জন্য আমাদের "ইগেনপাউস" (মুখের স্বীকৃতিতে "ইগেনফেসগুলি" এর মতো) একটি সেট তৈরি করতে হবে এবং প্রতিটি পাঞ্জা মুদ্রনকে এই ইগেনপাগুলির সংমিশ্রণ হিসাবে বর্ণনা করতে হবে। এটি মূল উপাদানগুলির বিশ্লেষণের অনুরূপ, এবং মূলত আমাদের ডেটার মাত্রিকতা হ্রাস করার একটি উপায় সরবরাহ করে, যাতে দূরত্বটি আকারের একটি ভাল পরিমাপ।
কারণ মাত্রা (2400 বনাম 400) এর চেয়ে বেশি প্রশিক্ষণের চিত্র আমাদের রয়েছে, গতির জন্য "অভিনব" রৈখিক বীজগণিত করার প্রয়োজন নেই do আমরা প্রশিক্ষণের ডেটা সেটের সমবায় ম্যাট্রিক্সের সাথে সরাসরি কাজ করতে পারি:
def make_eigenpaws(paw_data):
"""Creates a set of eigenpaws based on paw_data.
paw_data is a numdata by numdimensions matrix of all of the observations."""
average_paw = paw_data.mean(axis=0)
paw_data -= average_paw
# Determine the eigenvectors of the covariance matrix of the data
cov = np.cov(paw_data.T)
eigvals, eigvecs = np.linalg.eig(cov)
# Sort the eigenvectors by ascending eigenvalue (largest is last)
eig_idx = np.argsort(eigvals)
sorted_eigvecs = eigvecs[:,eig_idx]
sorted_eigvals = eigvals[:,eig_idx]
# Now choose a cutoff number of eigenvectors to use
# (50 seems to work well, but it's arbirtrary...
num_basis_vecs = 50
basis_vecs = sorted_eigvecs[:,-num_basis_vecs:]
return basis_vecs
এগুলি basis_vecs
হ'ল "ইগেনপাও"।
এগুলি ব্যবহার করার জন্য, আমরা কেবল ভিত্তি ভেক্টরগুলির সাথে প্রতিটি পা ইমেজ (20x20 চিত্রের পরিবর্তে 400-মাত্রিক ভেক্টর হিসাবে) ডট (অর্থাত্ ম্যাট্রিক্স গুণ) p এটি আমাদের একটি 50-মাত্রিক ভেক্টর দেয় (ভিত্তি ভেক্টরের প্রতি এক উপাদান) যা আমরা চিত্রটি শ্রেণিবদ্ধ করতে ব্যবহার করতে পারি। প্রতিটি "টেমপ্লেট" পাজের 20x20 চিত্রের সাথে 20x20 চিত্রের তুলনা করার পরিবর্তে, আমরা 50-মাত্রিক, রূপান্তরিত চিত্রটিকে প্রতিটি 50-মাত্রিক রূপান্তরিত টেম্পলেট পাটির সাথে তুলনা করি। প্রতিটি অঙ্গুলি ইত্যাদি ঠিক কীভাবে অবস্থিত হয় তাতে ছোট পার্থক্যের ক্ষেত্রে এটি অনেক কম সংবেদনশীল এবং মূলত সমস্যার মাত্রিক মাত্রাকে কেবলমাত্র প্রাসঙ্গিক মাত্রায় হ্রাস করে।
ইগেনপা-ভিত্তিক পাভ শ্রেণিবদ্ধকরণ
প্রতিটি পায়ে কোন পাটি যা শ্রেণিবদ্ধ করার জন্য এখন আমরা কেবল 50-মাত্রিক ভেক্টর এবং "টেম্পলেট" ভেক্টরগুলির মধ্যে দূরত্বটি ব্যবহার করতে পারি:
codebook = np.load('codebook.npy') # Template vectors for each paw
average_paw = np.load('average_paw.npy')
basis_stds = np.load('basis_stds.npy') # Needed to "whiten" the dataset...
basis_vecs = np.load('basis_vecs.npy')
paw_code = {0:'LF', 1:'RH', 2:'RF', 3:'LH'}
def classify(paw):
paw = paw.flatten()
paw -= average_paw
scores = paw.dot(basis_vecs) / basis_stds
diff = codebook - scores
diff *= diff
diff = np.sqrt(diff.sum(axis=1))
return paw_code[diff.argmin()]
এখানে ফলাফল কিছু আছে:
বাকি সমস্যা
এখনও কিছু সমস্যা রয়েছে, বিশেষত কুকুরগুলির সাথে একটি স্পষ্ট প্রশস্ততা তৈরি করার পক্ষে খুব ছোট ... (বৃহত কুকুরের সাথে এটি সবচেয়ে ভাল কাজ করে, কারণ পায়ের আঙ্গুলগুলি সেন্সরের রেজোলিউশনে আরও স্পষ্টভাবে পৃথক হয়ে যায়।) এছাড়াও, আংশিক প্যাপারপ্রিন্টগুলি এটির সাথে স্বীকৃত নয় সিস্টেম, তারা ট্র্যাপিজয়েডাল-প্যাটার্ন-ভিত্তিক সিস্টেমের সাথে থাকতে পারে।
যাইহোক, ইগেনপাওয়ার বিশ্লেষণ সহজাতভাবে একটি দূরত্বের মেট্রিক ব্যবহার করে, তাই আমরা "পাঞ্জা" উভয় উপায়ে শ্রেণিবদ্ধ করতে পারি এবং "কোডবুক" থেকে ইগেনপাওয়ার বিশ্লেষণের ক্ষুদ্রতম দূরত্বটি যখন কিছুটা প্রান্তিকের উপরে চলে যায় তখন আমরা ট্র্যাপিজয়েডাল-প্যাটার্ন-ভিত্তিক সিস্টেমে ফিরে যেতে পারি। যদিও আমি এখনও এটি প্রয়োগ করি নি।
ভাই ... এতদিন ছিল! আমার মজার টুপি আইভোর কাছে মজার একটি প্রশ্ন আছে!