2012-05-15 32 views
7

Tôi đang đọc Lập trình Python của John Zelle và tôi bị kẹt trên một bài tập được hiển thị trong hình bên dưới.Người mới bắt đầu bằng Python - Làm cách nào để đánh giá đường hồi qui từ các nhấp chuột và hiển thị đồ họa?

Bạn có thể xem mã của mình bên dưới. Tôi biết mã rất xấu. (Bất cứ lời khuyên được đánh giá cao)

Picture of Regression Exercise

Dưới đây là mã của tôi cho đến nay:

from graphics import * 

def regression(): 

# creating the window for the regression line 
     win = GraphWin("Regression Line - Start Clicking!", 500, 500) 
     win.setCoords(0.0, 0.0, 10.0, 10.0) 

     rect = Rectangle(Point(0.5, 0.1), Point(2.5, 2.1)) 
     rect.setFill("red") 
     rect.draw(win) 
     Text(rect.getCenter(), "Done").draw(win) 

     message = Text(Point(5, 0.5), "Click in this screen") 
     message.draw(win) 

     points = [] # list of points 
     n = 0 # count variable 
     sumX = 0 
     sumY = 0 

     while True: 
       p = win.getMouse() 
       p.draw(win) 

# if user clicks in a red square it exits the loop and calculates the regression line 
       if (p.getX() >= 0.5 and p.getX() <= 2.5) and (p.getY() >= 0.1 and p.getY() <= 2.1): 
         break 

       n += 1 # count of the points 

# get the sum of the X and Y points 
       sumX = sumX + p.getX() 
       sumY = sumY + p.getY() 

# tuple of the X and Y points 
       dot = (p.getX(), p.getY()) 
       points.append(dot) 

     avgX = sumX/n 
     avgY = sumY/n 

     top = 0 
     bottom = 0 

# my ugly attempt at the regression equation shown in the book 

     for i in points: 
       gp = 0 
       numer = points[gp][0] * points[gp][1] 
       top = top + numer 

       denom = points[gp][0] ** 2 
       bottom = bottom + denom 
       gp += 1 

     m = (top - sumX * sumY)/(bottom - sumX ** 2) 

     y1 = avgY + m * (0.0 - avgX) 
     y2 = avgY + m * (10.0 - avgX) 

     regressionline = Line(Point(0, y1), Point(10.0, y2)) 
     regressionline.draw(win) 

     raw_input("Press <Enter> to quit.") 
     win.close() 

regression() 

Khi tôi chạy chương trình đường hồi quy không bao giờ dường như là dòng thực sự của phù hợp nhất. Tôi tin rằng tôi đang giải thích phương trình hồi quy không chính xác trong mã của tôi. Những gì cần phải được thay đổi để có được đường hồi quy chính xác?

+0

Đây là lần đầu tiên SO câu hỏi của tôi. Hãy cho tôi biết nếu tôi nên hỏi điều này một cách khác nhau hoặc bao gồm thông tin nhiều hơn/ít hơn.Mã có quá dài để trích dẫn trực tiếp trong câu hỏi không? – TyShi

+1

Nếu bạn có thể xác định phần nào của mã mà bạn tự tin chịu trách nhiệm, có thể có ý nghĩa khi chỉ bao gồm phần đó; nhưng điều này không phải là _horrible_. Tôi đã xoay hình ảnh và đưa nó vào nội tuyến để giúp bạn dễ đọc hơn - điều này sẽ rất hay, nhưng có lẽ không thể cho một người mới. (Chào mừng bạn đến SO. :) – sarnold

+0

Sẽ tốt nếu hình ảnh được chuyển thành văn bản, nhưng Stack Overflow có hỗ trợ toán học theo cách math.se không? –

Trả lời

4

vấn đề:

  • from my_library import * nên tránh; tốt hơn để xác định chính xác những gì bạn muốn từ nó. Điều này giúp giữ cho không gian tên của bạn gọn gàng.

  • bạn đã có một khối mã lớn; tốt hơn để tách nó thành các chức năng riêng biệt. Điều này giúp bạn suy nghĩ và gỡ lỗi dễ dàng hơn nhiều và có thể giúp bạn sử dụng lại mã sau đó. Chắc chắn, đó là một vấn đề đồ chơi, bạn sẽ không tái sử dụng nó - nhưng toàn bộ các bài tập làm là để phát triển thói quen tốt, và bao thanh toán mã của bạn theo cách này chắc chắn là một thói quen tốt! Một nguyên tắc chung của ngón tay cái - nếu một hàm chứa nhiều hơn một tá dòng mã, bạn nên xem xét tách nó ra xa hơn.

  • bài tập yêu cầu bạn theo dõi x, y, xx và xy khi chạy các điểm đầu vào. Tôi nghĩ rằng đây là một ý tưởng tồi - hoặc ít nhất là C-ish hơn Python-ish - vì nó buộc bạn phải làm hai nhiệm vụ khác nhau cùng một lúc (nhận điểm và làm toán trên chúng). Lời khuyên của tôi sẽ là: nếu bạn đang nhận được điểm, có được điểm; nếu bạn đang làm toán, làm toán; đừng cố gắng làm cả hai cùng một lúc.

  • tương tự, tôi không thích cách bạn đã có tính toán hồi quy đáng lo ngại về vị trí các cạnh của cửa sổ. Tại sao nó nên biết hoặc quan tâm đến các cửa sổ? Tôi hy vọng bạn thích giải pháp của tôi để này ;-)

Dưới đây là phiên bản refactored của tôi về mã của bạn:

from graphics import GraphWin, Point, Line, Rectangle, Text 

def draw_window() 
    # create canvas 
    win = GraphWin("Regression Line - Start Clicking!", 500, 500) 
    win.setCoords(0., 0., 10., 10.) 
    # exit button 
    rect = Rectangle(Point(0.5, 0.1), Point(2.5, 2.1)) 
    rect.setFill("red") 
    rect.draw(win) 
    Text(rect.getCenter(), "Done").draw(win) 
    # instructions 
    Text(Point(5., 0.5), "Click in this screen").draw(win) 
    return win 

def get_points(win): 
    points = [] 
    while True: 
     p = win.getMouse() 
     p.draw(win) 
     # clicked the exit button? 
     px, py = p.getX(), p.getY() 
     if 0.5 <= px <= 2.5 and 0.1 <= py <= 2.1: 
      break 
     else: 
      points.append((px,py)) 
    return points 

def do_regression(points): 
    num = len(points) 
    x_sum, y_sum, xx_sum, xy_sum = 0., 0., 0., 0. 
    for x,y in points: 
     x_sum += x 
     y_sum += y 
     xx_sum += x*x 
     xy_sum += x*y 
    x_mean, y_mean = x_sum/num, y_sum/num 
    m = (xy_sum - num*x_mean*y_mean)/(xx_sum - num*x_mean*x_mean) 
    def lineFn(xval): 
     return y_mean + m*(xval - x_mean) 
    return lineFn 

def main(): 
    # set up 
    win = draw_window() 
    points = get_points(win) 
    # show regression line 
    lineFn = do_regression(points) 
    Line(
     Point(0., lineFn(0.)), 
     Point(10., lineFn(10.)) 
    ).draw(win) 
    # wait to close 
    Text(Point(5., 5.), "Click to exit").draw(win) 
    win.getMouse() 
    win.close() 

if __name__=="__main__": 
    main() 
+0

Tôi đã bị mắc kẹt về vấn đề này và giải pháp của bạn đã giúp tôi cam kết vô cùng. Tôi chưa bao giờ thấy một sub-def trước đó. Nó hoạt động như thế nào? Nó định nghĩa hàm nhưng không bao giờ thực sự được gọi, dường như trong thử nghiệm nó là mặc dù. –

3

vòng lặp for là tất cả điều sai lầm! bạn có một i rằng những thay đổi trong vòng lặp, nhưng sau đó sử dụng gp mà luôn luôn 0.

bạn muốn một cái gì đó giống như là:

for (X, Y) in points: 
    numer += X * Y 
    denom += X * X 

... hoặc di chuyển gp = 0 đến trước khi vòng lặp for.

... hoặc thả hoàn toàn phần đó và thêm sumXYsumXX vào sumXsumY.

một trong hai cách, một khi bạn khắc phục rằng nó phải là ok (tốt, hoặc có thể một số lỗi khác ....).

Các vấn đề liên quan